Pirates have finished developing the typing software. He called Cathy to test his typing software. She is good at thinking. After testing for several days, she finds that if she types a string by some ways, she will type the key at least. But she has a bad habit that if the caps lock is on, she must turn off it, after she finishes typing. Now she wants to know the smallest times of typing the key to finish typing a string.
InputThe first line is an integer t (t<=100), which is the number of test case in the input file. For each test case, there is only one string which consists of lowercase letter and upper case letter. The length of the string is at most 100.OutputFor each test case, you must output the smallest times of typing the key to finish typing this string.Sample Input
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问题就差不多啦~