1. 程式人生 > >POJ 1239 Increasing Sequences(經典的兩次dp)

POJ 1239 Increasing Sequences(經典的兩次dp)

style blank cnblogs open clu 一位 class blog 思路

http://poj.org/problem?id=1239

題意:
給出一串序列,現在要添加逗號作為分隔符,使得序列是遞增序列,然後讓最後一個數盡量小,第一個數盡量大。

思路:
先從頭到尾進行一次dp,d【i】表示分析到第i位時往前的最小長度,這樣一來,d【n】就表示最後一位的最小長度。

在滿足了最後一位盡量小的情況下,我們再從尾到頭進行一次dp,此時d【i】表示分析到第i位時往後的最大長度。思路和第一次dp是差不多的。

 1 #include<iostream>
 2 #include<algorithm>
 3 #include<cstring>
 4
#include<cstdio> 5 #include<sstream> 6 #include<vector> 7 #include<stack> 8 #include<queue> 9 #include<cmath> 10 #include<map> 11 #include<set> 12 using namespace std; 13 typedef long long ll; 14 typedef pair<int,int> pll; 15 const
int INF = 0x3f3f3f3f; 16 const int maxn = 80 + 5; 17 18 int d[maxn]; 19 char s[maxn]; 20 21 bool judge(int i, int j, int x, int y) //判斷【i,j】是否大於【x,y】 22 { 23 int len1=j-i+1; 24 int len2=y-x+1; 25 26 while(s[i]==0) {i++;len1--;} 27 while(s[x]==0) {x++;len2--;} 28 29
if(len1>len2) return true; 30 else if(len1<len2) return false; 31 else 32 { 33 for(int k=0; k<len1;k++) 34 { 35 if(s[k+i]>s[x+k]) return true; 36 else if(s[k+i]<s[x+k]) return false; 37 } 38 } 39 return false; 40 } 41 42 int main() 43 { 44 //freopen("in.txt","r",stdin); 45 while(~scanf("%s",s+1)) 46 { 47 int n=strlen(s+1); 48 if(n==1 && s[1]==0) break; 49 50 //從頭到尾找最小長度 51 for(int i=1;i<=n;i++) 52 { 53 d[i]=i; 54 for(int j=i-1;j>=1;j--) 55 { 56 if(judge(j+1,i,j-d[j]+1,j)) 57 { 58 d[i]=i-j; 59 break; 60 } 61 } 62 } 63 64 //從尾到頭找最大長度 65 int t=n-d[n]+1; //[t,n]已經是決定了的,不能改變 66 d[t]=d[n]; 67 for(int i=n-d[n];i>=1;i--) 68 { 69 if(s[i]==0) 70 { 71 d[i]=d[i+1]+1; 72 continue; 73 } 74 for(int j=t;j>i;j--) 75 { 76 if(judge(j,j+d[j]-1,i,j-1)) 77 { 78 d[i]=j-i; 79 break; 80 } 81 } 82 } 83 84 int tmp=d[1]+1; 85 for(int i=1;i<=n;i++) 86 { 87 if(tmp==i) 88 { 89 printf(","); 90 tmp=d[i]+i; 91 } 92 printf("%c",s[i]); 93 } 94 printf("\n"); 95 } 96 return 0; 97 }

POJ 1239 Increasing Sequences(經典的兩次dp)