題目轉自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之旅,未完待續.......