題目:SuSu's Powerspa
連接:http://acdream.info/problem?pid=1201code
題意:一我的站在x軸原點上,初始方向向x軸正方向,由一個字符串來控制其運動,字符串由A、B組成,A表示前進一步,B表示反向,給出字符串,問修改m次字符的狀況下,人離原點最遠多少?(能夠重複修改一個字符,可令 A變B 或 B變A)blog
思路:字符串
最近區間DP作多了,試了很久的區間DP。。。後來發現根本不須要用它(用了時間複雜度過高了。),由於必須把字符串完整用完,因此從第一個字符開始遞推就能夠了。後來改了方法,又由於不知道m次能夠針對同一個字符,錯了好屢次(思路也基本固定了,後來按原來思路稍加修改竟然闖下來了)。。。get
首先,我假定m次必須用完(。。。強裝我是故意的),用dp[105][55][2][2]計算,第一維表示下標,第二維表示修改次數,第三維表示方向(向右/向左),第四維表示最大或最小,dp[i][j][0][0]就表示解決前i 個字符,修改j次,當前方向是0的最大值(不是距離)。it
如今遞推式就很簡單了,按正常邏輯寫就能夠了,最終M次的答案就是dp[n-1][m][0][0], 01, 10, 11四個的絕對值求最大,必須都考慮,不能認爲方向0的最大值必定是正數,舉個例子BAB 0。io
最後解決m次能夠改變同一字符的狀況,假如我改了第一個字符兩次,就至關於m=m-2,因此取他們的較大值便可。class
AC代碼:方法
1 #include<stdio.h> 2 #include<algorithm> 3 using namespace std; 4 #define N 105 5 #define M 55 6 #define INF 1e9 7 /* 8 dp[i][j][k][x]: 9 i前,修改j次,當前是加/減,最大值/最小值 10 */ 11 int dp[N][M][2][2]; 12 void initdp() 13 { 14 for(int i=0; i<N; i++){ 15 for(int j=0; j<M; j++){ 16 for(int k=0; k<2; k++){ 17 for(int u=0; u<2; u++){ 18 dp[i][j][k][u]=-INF; 19 } 20 } 21 } 22 } 23 } 24 int add(int x, int y){ 25 if(x==-INF) return -INF; 26 return x+y; 27 } 28 int min(int x, int y) 29 { 30 if(x==-INF && y==-INF) return -INF; 31 else if(x==-INF) return y; 32 else if(y==-INF) return x; 33 else return x<y?x:y; 34 } 35 int main() 36 { 37 int n, m, cas=1; 38 char s[N]; 39 while(~scanf("%d", &n)){ 40 scanf("%s%d", s, &m); 41 initdp(); 42 if(s[0]=='A'){ 43 dp[0][0][0][0]=1; 44 dp[0][0][0][1]=1; 45 dp[0][1][1][0]=0; 46 dp[0][1][1][1]=0; 47 } 48 else{ 49 dp[0][0][1][0]=0; 50 dp[0][0][1][1]=0; 51 dp[0][1][0][0]=1; 52 dp[0][1][0][1]=1; 53 } 54 for(int i=1; i<n; i++){ 55 if(s[i]=='A'){ 56 dp[i][0][0][0]=add(dp[i-1][0][0][0],1); 57 dp[i][0][0][1]=add(dp[i-1][0][0][1],1); 58 dp[i][0][1][0]=add(dp[i-1][0][1][0],-1); 59 dp[i][0][1][1]=add(dp[i-1][0][1][1],-1); 60 for(int k=1; k<=m && k<=i+1; k++){ 61 dp[i][k][0][0]=max(add(dp[i-1][k][0][0], 1), dp[i-1][k-1][1][0]); 62 dp[i][k][0][1]=min(add(dp[i-1][k][0][1], 1), dp[i-1][k-1][1][1]); 63 dp[i][k][1][0]=max(add(dp[i-1][k][1][0], -1), dp[i-1][k-1][0][0]); 64 dp[i][k][1][1]=min(add(dp[i-1][k][1][1], -1), dp[i-1][k-1][0][1]); 65 } 66 } 67 else 68 { 69 dp[i][0][0][0]=dp[i-1][0][1][0]; 70 dp[i][0][0][1]=dp[i-1][0][1][1]; 71 dp[i][0][1][0]=dp[i-1][0][0][0]; 72 dp[i][0][1][1]=dp[i-1][0][0][1]; 73 for(int k=1; k<=m && k<=i+1; k++){ 74 dp[i][k][0][0]=max(add(dp[i-1][k-1][0][0], 1), dp[i-1][k][1][0]); 75 dp[i][k][0][1]=min(add(dp[i-1][k-1][0][1], 1), dp[i-1][k][1][1]); 76 dp[i][k][1][0]=max(add(dp[i-1][k-1][1][0], -1), dp[i-1][k][0][0]); 77 dp[i][k][1][1]=min(add(dp[i-1][k-1][1][1], -1), dp[i-1][k][0][1]); 78 } 79 } 80 } 81 82 //int x, y, z, k; 83 //while(~scanf("%d%d%d%d", &x, &y, &z, &k)){ 84 // printf("==> %d\n", dp[x][y][z][k]); 85 //} 86 87 int ans=-INF; 88 while(m>=0) 89 { 90 int tmp=-INF; 91 if(dp[n-1][m][1][1]!=-INF && dp[n-1][m][0][0]!=-INF) 92 tmp=max(abs(dp[n-1][m][0][0]), abs(dp[n-1][m][1][1])); 93 else if(dp[n-1][m][0][0]!=-INF) tmp=abs(dp[n-1][m][0][0]); 94 else if(dp[n-1][m][1][1]!=-INF) tmp=abs(dp[n-1][m][1][1]); 95 96 if(dp[n-1][m][1][0]!=-INF && dp[n-1][m][0][1]!=-INF) tmp = max(tmp, max(abs(dp[n-1][m][0][1]), abs(dp[n-1][m][1][0]))); 97 else if(dp[n-1][m][1][0]!=-INF) tmp=max(tmp, abs(dp[n-1][m][1][0])); 98 else if(dp[n-1][m][0][1]!=-INF) tmp=max(tmp, abs(dp[n-1][m][0][1])); 99 100 ans=max(ans, tmp); 101 m-=2; 102 } 103 104 printf("Case #%d: %d\n", cas++, ans); 105 } 106 return 0; 107 }