HDU 2577:How to Type(动态规划或模拟)

How to Type

Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others)
Total Submission(s): 6036    Accepted Submission(s): 2708


Problem Description
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
题目意思:
就是敲最少的按键把题目所给的单词打出来。我们知道如果cap没按下,且现在要打一个大写字母,可以通过shift+小写字母,也可以选择先按
cap然后再按字母,如果cap已经按下了,这个时候要打小写字母,可以按shift+这个小写字母。或按一下cap在小写字母。
题目代码:
#include<iostream>
#include<stdio.h>
#include<cstring>
#include<algorithm>
#define min(a,b)a<b?a:b
#define INF 0x3f3f3f3f
using namespace std;
int main()
{
    char a[200];
    int on[200],off[200];//on数组代表打当前字母时Caps Lock灯当前是亮的,off数组代表打当前字母时灯是灭的。
   int N,i,len;
   scanf("%d",&N);
   while(N--)
   {
     scanf("%s",a);
     len=strlen(a);
     on[0]=1;   //最初灯是灭的,如果起初我们要让灯亮起来,那我们要按一下cap键,费时一秒,初始时间为1
     off[0]=0;  //灯刚开始不亮的,所以off数组的初始化为0。代表最初没有按一下键
     for(i=0;i<len;i++)
     {
         if(a[i]>='a'&&a[i]<='z')//如果是小写字母
         {
             on[i+1]=min(on[i]+2,off[i]+2);//如果打完这个字母灯是亮的
//如果打这个字母之前灯是亮的,那么我可以(shift+type,两秒),也可以(关灯,type,开灯,三秒)如果要时间短的话,之前灯是开的,我们就选择方法//1,在上一个on上加+2
//如果打之前灯是灭的,打完后灯亮,那么我可以(type,开灯,2),页可以(开灯,shift,type,3)如果要时间短的话,之前灯是关的,我们就选择方法1,在off上+2
             off[i+1]=min(on[i]+2,off[i]+1); //如果打完这个字母灯是关着的
//如果打之前灯是亮的,打完灯是灭的,那么我可以(shift,type,关灯),也可以(关灯,type,2),如果要时间短,之前灯是开的,我们就选择方法2,在on上+2.
//如果打之前灯是关的,打完灯是关的,直接type打出小写字母最快,只要1秒
         }
         else //如果当前要打的字母是大写字母
         {
             on[i+1]=min(on[i]+1,off[i]+2);  //如果打完这个字母灯是开的
//原来灯是开的,直接打出字母即可,只需要一秒,如果原来灯是关的,那我们(开灯,type,2),也可以(shift,type,开灯,3),选省时间的
             off[i+1]=min(on[i]+2,off[i]+2); //如果打完这个字母灯是关着的
//原来灯开,(type,关灯,2),或(关灯,shift,type)选时间短的,原来灯是关的(shift,type,2),或(开灯,type,关灯,3),选择时间短的
         }
     }
     on[len]++;    //最后灯必须是关着的,所以要按一次cap,最后灯开时的时间+1,将灯关上。
     printf("%d\n",min(on[len],off[len]));
   }
   return 0;
}

 还可以直接模拟着做:

定义bool变量flag来标记大写锁定键灯的开和关,当灯打开时用true表示,当灯关闭的时候用flase来表示。现在讨论情况

如果当前灯时打开着的:
如果当前要打的字母时大写字母,直接打过去,花费一秒。
如果当前要打的字母时小写时,我们需要考虑下一个字母的状态,如果下一个字母时小写的,我们应该把灯关注,然后再
打,因为关灯的打的话,打完这两个字母花费的时间时3秒,不关的话花费的时间时四秒。如果下一个字母时大写字母,则
不要关灯,因为关灯的话,打小写两秒,打大写也是两秒,就是4秒时间,不关灯的话,打小写2秒,打大写一秒就是3秒。

如果当前灯是关闭的:
如果当前要打的字母是小写字母,直接打过去,花费一秒。
如果当前要打的字母是大写字母,则需要看下一个字母的状态,如果下一个字母是大写,则把灯按开,因为这样的话,打这
来给你个字母花费3秒,否则花费4秒。如果下一个字母是小写,开灯的话,打两个字母花费4秒,不开灯的话是三秒。

对于前len-1个字母的计算都按上面的来,因为第len个字母没有下一个字母,所以我们不能这样来做。

对于最后一个字母单独考虑:(打完字之后灯一定时关着的)
如果打最后一个字母前灯是开着的,则无论最后一个字母是大写还是小写,都会花费两秒的时间。
如果打最后一个字母前灯是关着的,则如果最后一个字母是大写,就要花两秒,如果是小写就花费一秒。

AC代码如下:
#include <iostream>
#include <stdio.h>
#include <string.h>

using namespace std;

char str[1000];
int main()
{
    int t;
    scanf("%d",&t);
    while(t--)
    {
        scanf("%s",str);
        bool flag = false;
        int ans = 0;
        int len = strlen(str);
        for(int i = 0; i < len-1; i++)
        {
            if(flag)  ///当前灯是亮着的
            {
                if(str[i]>='A'&&str[i]<='Z')  ///又是大写字母,直接打过去
                    ans++;
                else   ///这个位置是小写
                {
                    if(str[i+1]>='a'&&str[i+1]<='z')
                    {
                        flag = false;   ///关灯
                        ans += 2;
                    }
                    else ///下一个是大写
                    {
                        ans += 2;
                    }
                }
            }
            else   /// 灯是灭着的
            {
                if(str[i]>='a' && str[i]<='z')
                {
                    ans++;
                }
                else
                {
                    if(str[i+1]>='A' && str[i+1]<='Z')
                    {
                        flag = true;
                        ans += 2;
                    }
                    else
                        ans += 2;
                }
            }
        }
        if(flag)  ///灯是开着的
        {
            ans+=2;
        }
        else
        {
            if(str[len-1]>='a'&&str[len-1]<='z')
            {
                ans++;
            }
            else
                ans += 2;
        }
        printf("%d\n",ans);
    }
    return 0;
}



  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值