sdut1650I-Keyboard(dp)
题目大意就相当于 跟你一串字符串 让你截成k段 使总体的值最小
想法是递归的 递归太慢 可以转换为递推的
这样就有可以推出状态方程 dp[i][j] = max(dp[i][j],dp[i-1][g]+sum[g+1][j]+sum[1][g]-sum[1][j]); dp[i][j]表示总长度为j第i次截的最小值 后面的sum[i][j]表示的就是从i开始作为第一个到j个的花费 o[i][j]保存路径
1 #include <iostream> 2 #include<cstdio> 3 #include<cstring> 4 #include<algorithm> 5 #include<stdlib.h> 6 #include<algorithm> 7 #include<vector> 8 #include<cmath> 9 #define INF 1e10 10 using namespace std; 11 char s[100],ks[100]; 12 #define LL long long 13 LL dp[100][100],p[100],sum[110][100]; 14 int o[100][100],pa[100]; 15 int main() 16 { 17 //freopen("data1.in","r",stdin); 18 //freopen("text.out","w",stdout); 19 int t,k,i,j,l,g,kk=0; 20 cin>>t; 21 while(t--) 22 { 23 memset(sum,0,sizeof(sum)); 24 kk++; 25 for(i = 0; i < 100 ; i++) 26 for(j = 0 ; j < 100 ; j++) 27 dp[i][j] = INF; 28 cin>>k>>l; 29 cin>>ks; 30 cin>>s; 31 for(i = 1; i <= l ; i++) 32 cin>>p[i]; 33 for(i = 1; i <= l ; i++) 34 { 35 for(j = i; j <= l ; j++) 36 sum[i][j] = sum[i][j-1]+p[j]*(j-i+1); 37 } 38 for(i = 1 ;i <= k-1 ; i++) 39 for(j = l ; j >= 1 ; j--) 40 for(g = 1 ; g < j ; g++) 41 { 42 if(dp[i][j]>dp[i-1][g]+sum[1][g]+sum[g+1][j]-sum[1][j]) 43 { 44 dp[i][j] = dp[i-1][g]+sum[1][g]+sum[g+1][j]-sum[1][j]; 45 o[i][j] = g; 46 } 47 } 48 int x = k-1,y = l; 49 g = 0; 50 while(x) 51 { 52 pa[++g] = o[x][y]; 53 x--;y = pa[g]; 54 } 55 printf("Keypad #%d:\n",kk); 56 pa[g+1] = 0; 57 for(i = g ;i >= 1 ;i--) 58 { 59 printf("%c: ",ks[k-i-1]); 60 for(j =pa[i+1]+1; j <= pa[i] ; j++) 61 { 62 printf("%c",s[j-1]); 63 } 64 puts(""); 65 } 66 printf("%c: ",ks[k-1]); 67 for(j = pa[1]+1; j <= l ; j++) 68 printf("%c",s[j-1]); 69 puts(""); 70 puts(""); 71 } 72 return 0; 73 } 74 75 76 77 78 /************************************** 79 Problem id : SDUT OJ 1650 80 User name : shang 81 Result : Accepted 82 Take Memory : 688K 83 Take Time : 200MS 84 Submit Time : 2014-02-15 11:17:10 85 **************************************/