题目转自hdu 2577,题目传送门php
题目大意:c++
现给你n个区分大小写的字符串,大小写可用Caps Lock和shift切换(学过计算机的都知道)测试
可是有一点须要注意(shift是切换,若如今是大写锁定,用shift可切换成小写)spa
这道题一开始拿的时候,就以为是n2的dpcode
可是,转移方程一直没想出来(耗时0.25h)blog
后来又仔细想一想,发现是2n的dp字符串
而后想了想,20min就切了get
解题思路:it
咱们先将字符串作预处理,造成一个01字符串io
像这个测试数据:
HELlowORLd
能够转换成这样:
1110001110
而后,就能够写转移方程了
若是目前的字符须要大写,就是这样:
dp[i][0]=min(dp[i-1][0]+1,dp[i-1][1]+1)+1; dp[i][1]=min(dp[i-1][0]+1,dp[i-1][1])+1;
dp[i][0]表明第i个字符,有大写锁定,dp[i][1]表明第i个字符,无大写锁定
若不须要大写,则是这样:
dp[i][0]=min(dp[i-1][1]+1,dp[i-1][0])+1; dp[i][1]=min(dp[i-1][1]+1,dp[i-1][0]+1)+1;
(意思本身理解,暴怒蒟蒻在线虐人)
而后就很简单了,AC代码以下(码风清奇,请勿怪罪)
#include<bits/stdc++.h> using namespace std; char s[110]; int n,t[110],dp[110][2]; int main() { scanf("%d",&n); for(int i=1;i<=n;i++) { memset(t,0,sizeof(t)); scanf("%s",&s); int l=strlen(s); for(int i=0;i<l;i++) if(s[i]>=65 && s[i]<=90) t[i]=1;//预处理 dp[0][1]=2; if(t[0]==1) dp[0][0]=2; else dp[0][0]=1;//初始化 for(int i=1;i<l;i++) { if(t[i]==1) { dp[i][0]=min(dp[i-1][0]+1,dp[i-1][1]+1)+1; dp[i][1]=min(dp[i-1][0]+1,dp[i-1][1])+1; } else { dp[i][0]=min(dp[i-1][1]+1,dp[i-1][0])+1; dp[i][1]=min(dp[i-1][1]+1,dp[i-1][0]+1)+1; }//转移方程 } printf("%d\n",min(dp[l-1][0],dp[l-1][1]+1));//还须要比较 } return ~~(0-0);//装个13 }
就这样,这道题就能够轻松AC了......
dp之旅,未完待续.......