HDU 2577 How to Type

传送门

多阶段决策dp。

给你一个只包含大小写字母的字符串,问你打这个字符串最少按多少次键。
这题也是够傻逼了。说几点需要注意的:

  1. 大小写转换不仅可以用capslock,还可以用shift。(通过样例得知)
  2. 它说的题意是指“在打完所有字后,如果大小写锁定还开着,那么就关闭”。并不是下一个字符是小写字母了就要关capslock。
  3. 下一个字符是小写字母了但如果就是不关capslock该怎么操作?很简单,此时shift的作用正好相反(还有这种操作?)。
  4. 这题没考虑过shift一直按着这种操作,这道题所认知的shift只能对按下shift后打的第一个字符生效。

不要去想有多少种可能出现的字符模式,不要纠结这些。就按照多阶段决策就完事了,关键就在于怎么设计状态、怎么设计每个阶段的状态才能明确(想出来)状态转移过程
dp[1 or 2][i]表示打完前i个字符后,capslock分别是开启、关闭情况下的最少打字数。根据当前字符的大小写,分情况由上个字符的两个状态得出。

为什么不加上shift的状态?shift在哪里体现?因为shift只能管它的下一个字符,可以蕴含在上述的状态转移过程中。


#include <cstdio>
#include <iostream>
#include <algorithm>
#include <vector>
#include <cstring>
#include <string>
#include <queue>
#include <cctype>                    // 可以使用isupper('c'),islower('c')
using namespace std;

int T;
char str[110];
int on[110], off[110];               // 输入第i位字符后CapsLock分别是开启、关闭状态下的最小打字数

int main()
{
	scanf("%d", &T);
	for (; T--;)
	{
		scanf("%s", str);
		if (isupper(str[0]))
		{
			on[0] = 2;
			off[0] = 2;
		}
		else
		{
			on[0] = 2;
			off[0] = 1;
		}
		for (int i = 1; i < strlen(str); i++)
		{
			if (isupper(str[i]))
			{
				on[i] = min(on[i - 1] + 1, off[i - 1] + 2);
				off[i] = min(on[i - 1] + 2, off[i - 1] + 2);
			}
			else
			{
				on[i] = min(on[i - 1] + 2, off[i - 1] + 2);
				off[i] = min(on[i - 1] + 2, off[i - 1] + 1);
			}
		}
		printf("%d\n", min(off[strlen(str) - 1], on[strlen(str) - 1] + 1));  // 别忘了最后的on[]还得加一
	}
	
	return 0;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值