POJ 1239 Increasing Sequences(经典的两次dp)
Posted 谦谦君子,陌上其华
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了POJ 1239 Increasing Sequences(经典的两次dp)相关的知识,希望对你有一定的参考价值。
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)的主要内容,如果未能解决你的问题,请参考以下文章
Storyboard & Seque:展示的 VC 如何知道展示的 VC 啥时候解散自己?