R - How to Type(线性DP)

害,真是太难了、、
原题:

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.
Input
The 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.
Output
For each test case, you must output the smallest times of typing the key to finish typing this string.
Sample Input
3
Pirates
HDUacm
HDUACM
Sample 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

翻译:
这个题的意思就是来求最少按的键盘的数量,初始的是小写字母,按成大写字母可以通过长按shift或者按capslk来切换。求出打出字符串需要俺的最少键盘数。
感慨:
做了这么一阵的线性DP,真的是大部分题没有思路就算有思路做题也不知所措。感觉DP太难了。或许还没有找到方法。
思路:
这个题刚开始的思路没想用dp做感觉如果单个大写字母出现就把他标记成 2 如果多个出现多个的个数在+2最后求和求出最小按键数、但是感觉不用dp做的话应该不对就没多想,按照线性dp的步骤——》第一步来找状态这里的状态不是很好找,刚开始想找到达第i个数需要的最小按键数,但是发现再找最小按键数的时候,我们还有一个关系没有考虑,那就是在第i个的时候是否是大小写。所以这样我们就要用两个dp数组分表表示第i和时候是大写的最小按键数和到达第i个的时候的最小按键数。那么我们找到状态之后我们就进行第二步——来找状态转移方程 因为状态转移方程是来表示第i个的最小按键数,所以我们需要来判断第i的时候的字母大小写。
分为这几种情况:
dp1[i]//表示大写关闭。
dp2[i]//表示大写打开。
1、第i个数为小写:
(1)大写处于关闭:
dp1[i]=min(dp1[i-1]+1,dp1[i-1]+2);
(2)大写处于打开:
dp2[i]=min(dp1[i-1]+2,dp2[i-1]+2);
2、第i个位大写:
(1)大写处于关闭:
dp1[i]=min(dp[i-1]+2,dp2[i-1]+2);
(2)大写处于打开:
dp2[i]=min(dp1[i-1]+2,dp[i-1]+1);
这是考虑的各个情况。之前看这个状态转移方程还有点不明白,在写这个博客的时候突然就明白了。
写完状态转移方程之后就是第三步——初始化这个的初始化还是挺好看的如果第一个是大写就为2,反之、为1;
最后代码如下:

#include<iostream>
#include<algorithm>
#include<math.h>
#include<stdio.h>
#include<cstring>
#include <queue>
#include<iomanip>
#include<string>
#include<map>

using namespace std;

int dp[1100];//小写,
int dp1[1100];//大写
int main()
{
   int t;
   cin>>t;
   while(t--)
   {
      string s;
       cin>>s;
       int n;
       n=s.size();
       if(s[0]>='A'&&s[0]<='Z')
           {dp1[0]=2;dp[0]=2;}
           else
            {dp[0]=1;dp1[0]=2;}
       for(int i=1;i<n;i++)
       {
           if(s[i]>='A'&&s[i]<='Z')
           {
               dp1[i]=min(dp[i-1]+2,dp1[i-1]+1);
               dp[i]=min(dp[i-1]+2,dp1[i-1]+2);
           }
            if(s[i]>='a'&&s[i]<='z')
            {
                dp[i]=min(dp[i-1]+1,dp1[i-1]+2);
                dp1[i]=min(dp[i-1]+2,dp1[i-1]+2);
            }

       }
       cout<<min(dp[n-1],dp1[n-1]+1)<<endl;
   }
}

总结:
写完这篇博客感觉线性dp没有啥途径,主要就是靠多做题多整理,或许在看别人的代码的时候看不太懂整理整理或许就能明白。

评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

晨晓翔同学

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值