一、标题统计
题目要求我们要输入一个字符串,并计算除空格外的字符个数:
从给定的数据规模可知,我们最多只需要输入5个字符长度的字符串即可。代码实现如下:
#include <iostream>
using namespace std;
int main(){
string s;
int cnt=0;
getline(cin, s);
int n = s.length();
if(n == 0 ) return 0;
for(int i=0; i<n; ++i){
if(s[i] != ' ') ++cnt;
}
cout << cnt << endl;
}
参考答案代码:
#include <iostream>
#include <cstdlib>
#include <string>
int main() {
freopen("./title/title4.in", "r", stdin);
freopen("title.out", "w", stdout);
std::string s;
std::getline(std::cin, s);
int cnt = 0;
if (s.length() > 0 && s[0] != ' ') ++cnt;
if (s.length() > 1 && s[1] != ' ') ++cnt;
if (s.length() > 2 && s[2] != ' ') ++cnt;
if (s.length() > 3 && s[3] != ' ') ++cnt;
if (s.length() > 4 && s[4] != ' ') ++cnt;
std::cout << cnt << std::endl;
return 0;
}
二、龙虎斗
算法思想:
题目要求输出派遣的兵营编号,使双方的势力相差尽可能地少,设龙势力值为,虎势力值为,我们先要判断龙虎方谁家的势力大些,若则可能派往虎方,若则可能派往龙方,若则派往。
代码如下:
#include <cstdio>
#include <climits>
// 定义长整型,防止数据溢出
typedef long long LL;
const int N = 100000;
int n, m, p1;
LL c[N], s1, s2;
// 取绝对值操作
LL ABS(LL x) { return x < 0 ? -x : x; }
int main() {
//输出n个节点并赋予权值
scanf("%d", &n);
for (int i = 1; i <= n; ++i) {
scanf("%lld", &c[i]);
}
scanf("%d%d%lld%lld", &m, &p1, &s1, &s2);
//(m - p1) * s1代表天降神兵,为负表示在虎方,为正表示在龙方。
//best定义双方实力差距,k代表输出的兵营
LL sum = (m - p1) * s1, best = LLONG_MAX; int k = -1;
//此时sum代表双方的势力差距
for (int i = 1; i <= n; ++i) {
sum += (m - i) * c[i];
}
//求取最小的派遣方案,并输出派遣的兵营号
for (int i = 1; i <= n; ++i) {
LL tmp = ABS(sum + (m - i) * s2);
if (tmp < best) {
best = tmp;
k = i;
}
}
printf("%d\n", k);
return 0;
}
三、摆渡车
算法思想:
题目要求最后一班车出发后所有人等待的最短时间。我们假设最后一班车出发的时间为,则倒数第二班车出发的时间取值应该为这样才能保证最后哦一班车在t[n]时间点准时出发,若倒数第二班车早于,若期间无人到达则无需发车,若期间有人则完全可以先发车才能使所有的等待时间最短,故若期间有人其必定不是倒数第二班车,若期间无人则时间距离可以设置为2*m,不影响最终结果。
代码实现:
#include <cstdio>
#include <algorithm>
using namespace std;
const int N = 500, M = 100, T = 2*M*N, INF = 0X7FFFFFFF;
int n, m, ans=INF, t[N], c[N], d[T], wt[T], nums[T], sum[T];
// c[i]代表连续两个到达的人之间的时间间隔
// 数组wt[T],wt[i]表示在时间点i之前包含时间点i到达的所有人,乘坐第i分钟出发的车,总的等待时间;
// nums[i]记录在时间点i到达的人数。
// sum[i]记录在时间点i之前包含时间点i到达的人数。
// d[i]表示最后一班车在i分钟发车,最小的总等待时间;
// d[i] = min(d[j] + wait(j+1, i)), j是上一班车的发车时间,j∈(i-2m, i-m];
// wait(i,j)表示在j和i之间到达的人,搭乘i分钟出发的车所需的等待时间。wait(i,j)=wt[i]-wt[j]-(i-j)*sum[j]
// ans = min(d[i]); i∈[t[n], t[n]+m)
int main(){
scanf("%d %d", &n, &m);
// 存储n个人到达的时间点
for(int i=1; i<=n; i++) scanf("%d", &t[i]);
// 将n个人到达的时间点进行有序排列
sort(t+1, t+1+n);
// 差分数组
for(int i=1;i<=n;i++) c[i] = t[i] - t[i-1];
// t[1]设为2*m为了保证后面计算j = i-2*m+1 > 0, 且t[1]代表第一班车的发车时间不影响最后结果
t[1] = 2 * m, nums[t[1]] = 1 ;
// 枚举连续两个时间段的距离,若大于2*m可以直接取值为2*m不影响结果
// 并为每个人到达的时间点进行重新定义,主要因为t[1]值换了
for(int i=2;i<=n;i++){
if(c[i]>2*m) c[i]=2*m;
t[i]=t[i-1]+c[i];
nums[t[i]]++;
}
// 枚举计算最后一班车的发车时间
for(int i=t[1];i<t[n]+m;i++){
// 没延后一分钟,前面的人sum[i-1]就多等一分钟
wt[i] = wt[i-1] + sum[i-1]*1;
sum[i] = sum[i-1] + nums[i];
d[i] = wt[i];
}
for(int i=t[1];i<t[n]+m;i++)
for(int j=i-2*m+1;j<=i-m;j++)
d[i]=min(d[i], d[j]+wt[i]-wt[j]-(i-j)*sum[j]);
for(int i=t[n];i<t[n]+m;i++) ans=min(ans, d[i]);
printf("%d", ans);
return 0;
}
四、对称二叉树
算法思想:对称二叉树其实就是对应的左右子树互换位置与原来一样,即左子树节点的值等于右子树节点的值。算法实现如下:
#include <iostream>
#include <algorithm>
using namespace std;
// 依题意知:n<=10^6
const int Size = 1e6+10;
const int INF = 0x3f3f3f3f;
# define ll long long;
// 根据n个节点创建树
struct Tree{
int v, Left_Child, Right_Child;
}tree[Size];
void DFS(int L, int R);
// n为节点树,sum为对称二叉树的根节点树,ans为结果
int n, sum=1, ans=1;
//递归标值
bool F=true;
int main(){
scanf("%d", &n);
for (int i = 1; i <= n; i++) scanf("%d", &tree[i].v);
for (int i = 1; i<=n;i++) scanf("%d%d", &tree[i].Left_Child, &tree[i].Right_Child);
for (int i=1; i<=n; i++){
F = true;
sum=1;
DFS(tree[i].Left_Child, tree[i].Right_Child);
if(F) ans = max(ans, sum);
}
cout << ans;
return 0;
}
//深度遍历二叉树
void DFS(int L, int R){
if(F == false) return;
if (L == -1 && R == -1) return;
if ((L == -1 && R !=-1) || (L != -1 && R == -1)){
F = false;
return;
}
if (tree[L].v == tree[R].v){
sum+=2;
DFS(tree[L].Left_Child, tree[R].Right_Child);
DFS(tree[L].Right_Child, tree[R].Left_Child);
}
else{
F = false;
return;
}
}