3 Pirates HDUacm HDUACMSample Output
8
8
8
Hint
The string “Pirates”, can type this way, Shift, p, i, r, a, t, e, s, the answer is 8. The string “HDUacm”, can type this way, Caps lock, h, d, u, Caps lock, a, c, m, the answer is 8 The string "HDUACM", can type this way Caps lock h, d, u, a, c, m, Caps lock, the answer is 8
解题思路:这个题跟上一篇我的博客里的vacations是一个思路,都是用一个二维数组dp[i][j]表示最小值,其中j表示的是状态,在上篇博客vacations中j有三个值,代表三种状态,这个题只有两种状态,j为0时表示打完第i个字符之后当前的键盘锁定是小写字母,j为1时表示打完第i个字符后当前的键盘锁定是大写字母。于是我们可以得出状态转移方程: dp[i][0] 和dp[i][1].从dp[i-1][0]得到dp[i][0],如果当前的s[i]字符是小写字母,则很简单就直接敲入当前字符,就是dp[i][0]+1;r如果当前的是大写字母就按Shift再按字符,就是dp[i-1][1]+2; 同理从dp[i-1][1]得到dp[i-1][0],如果当前的字母是小写字母就是先按下Lock再按下字符,就是dp[i-1][1]+2,如果当前是大写字母就按下字母再按Lock,就是dp[i-1][1]+2;这里最后的答案就是min(dp[n][0],dp[n][1])
这里需要我们注意的是dp[][]的初始化,因为这是求最小值,所以初始化要用到无穷大,但是因为dp[0][0]是开始状态,所以dp[0][0]的初始值设为0,而dp[0][1]设为1因为按下lock键才会变成大些锁定,还有最后的一步dp[n][1]+1;因为最后要把键盘设置成初始态。
AC代码:
#include<iostream>
#include<string>
#include<algorithm>
int dp[105][2];
using namespace std;
string s;
int T;
int main()
{
scanf("%d", &T);
while (T--)
{
cin >> s;
int n = s.length();
memset(dp, 0x3f, sizeof(dp));
dp[0][0] = 0;
dp[0][1] = 1;
for (int i = 1; i <= n; i++)
{
if (s[i - 1] - 'a' >= 0 && s[i - 1] <= 'z')
{
dp[i][0] = min(dp[i - 1][0], dp[i - 1][1] + 1) + 1;
dp[i][1] = min(dp[i - 1][0] + 1, dp[i - 1][1] + 1) + 1;
}
if (s[i - 1] - 'A' >= 0 && s[i - 1] <= 'Z')
{
dp[i][1] = min(dp[i - 1][1], dp[i - 1][0] + 1) + 1;
dp[i][0] = min(dp[i - 1][1] + 1, dp[i - 1][0] + 1) + 1;
}
}
dp[n][1] = dp[n][1] + 1;
printf("%d\n", min(dp[n][0],dp[n][1]));
}
return 0;
}
到这里,基本的dp问题就差不多啦~