大小写转换
题目大意
直接写a,会花费x的时间,写shift+a,会花费y的时间,打开caplocks,会花费z的时间,请问打一串a和A的字符串,最少花费的时间;
算法分析
\(f[i][0/1]\)表示写到第i个字符的时候,caplocks是否是打开的状态,0表示没有打开,1表示打开
if(s[i]=='a'){f[i][0]=min(f[i-1][0]+x,f[i-1][1]+z+x);//不打开caplocksf[i][1]=min(f[i-1][0]+z+y,f[i-1][1]+y);//
}
if(s[i]=='A'){f[i][0]=min(f[i-1][0]+y,f[i-1][1]+z+y);f[i][1]=min(f[i-1][0]+z+x,f[i-1][1]+x);
}
初始状态是\(f[0][0]=0\),最终状态是\(min(f[n][1],f[n][0]);\)
数字反转
题目大意
改变i,会使得a[i],a[i+1]都乘以-1,问如何操作使得最后的a数组的和最大
3
-10 5 -4
第一次改变,10 -5 -4
第二次改变 10 5 4,所以最终答案是19
算法分析
我们观察性质发现,最终\(a[i]\)的值是被i和i-1是否改变影响的,所以我们可以设置\(f[i][0/1]\)表示前i位获得的最大值,且第i位是否改变的;
f[0][1] = INT_MIN;for (int i = 1; i <= n - 1; i++) {f[i][0] = max(f[i - 1][1] - a[i], f[i - 1][0] + a[i]);f[i][1] = max(f[i - 1][1] + a[i], f[i - 1][0] - a[i]);}f[n - 1][0] += a[n];//必须把最后的a[n]加入到答案中f[n - 1][1] -= a[n];cout << max(f[n - 1][0], f[n - 1][1]);
核电站
题目大意
有n个坑,连续放m个就会爆炸,问最后的方案数
想答案最终合法的状态是第i个坑前面连续放了\(0,1,2,3,……m-1\)个,所以\(f[i][j]\)表示前\(i\)个坑里,连续放了\(j\)个核炸弹的方案数
f[0][0] = 1;for (int i = 1; i <= n; i++) {for (int j = 0; j <= min(m - 1, i); j++) {f[i][0] += f[i - 1][j]; //如果第i个位置不放f[i][j] %= mod;if (j >= 1) {f[i][j] += f[i - 1][j - 1];f[i][j] %= mod;}}}for (int i = 0; i <= min(n, m - 1); i++) {ans += f[n][i];ans %= mod;}