HDU 2577 DP 题解
2019-11-30
Written by WSY
1.题目传送门:http://acm.hdu.edu.cn/showproblem.php?pid=2577
2.题目思路: 这道题看上去是一道字符串模拟,虽然我最开始也是这样做的,但正确的做法应该是DP。在大家的认知中,DP应该使用与解决一些类似于石子合并,能量项链那样的题,这道题怎么会用到DP呢??
我们假设dp[i][0]表示现在没开大写锁定,dp[i][1]表示现在开了大写锁定,这样的话就可以推出这样的递推表达式:
dp[i][1]=min(dp[i-1][1]+2,dp[i-1][0]+2); dp[i][0]=min(dp[i-1][1]+2,dp[i-1][0]+1);
哦,对了,这样几句话之前还要先判断这个字符是不是大写/小写:
bool checksmall(char a) { if(a>='a'&&a<='z') return true; if(a>='A'&&a<='Z') return false;
}
所以经过这样的更改后的代码就是这个压子的:
if(checksmall(a[i-1])) { dp[i][1]=min(dp[i-1][1]+2,dp[i-1][0]+2); //1 capslock dp[i][0]=min(dp[i-1][1]+2,dp[i-1][0]+1); } else { dp[i][1]=min(dp[i-1][1]+1,dp[i-1][0]+2); dp[i][0]=min(dp[i-1][1]+2,dp[i-1][0]+2); }
最后给一个福利:
#include<bits/stdc++.h> using namespace std; bool checksmall(char a) { if(a>='a'&&a<='z') return true; if(a>='A'&&a<='Z') return false; } int dp[100001][2]; int main() { int n; char a[100001]; scanf("%d",&n); while(n--) { memset(dp,0x3f,sizeof(dp)); cin>>a; int l=strlen(a); dp[0][0]=0; dp[0][1]=1; for(int i=1;i<=l;i++) { if(checksmall(a[i-1])) { dp[i][1]=min(dp[i-1][1]+2,dp[i-1][0]+2); //1 capslock dp[i][0]=min(dp[i-1][1]+2,dp[i-1][0]+1); } else { dp[i][1]=min(dp[i-1][1]+1,dp[i-1][0]+2); dp[i][0]=min(dp[i-1][1]+2,dp[i-1][0]+2); } } //if(cpos==1) ans++; printf("%d\n",min(dp[l][0],dp[l][1]+1)); } return 0; }
谢谢大家!