ZOJ 2702 Unrhymable Rhymes(DP)
题目链接:http://acm.zju.edu.cn/onlinejudge/showProblem.do?problemId=1702
题目大意:给定有很多数字组成的诗,譬如 “AABB”, “ABAB”, “ABBA” and “AAAA”形式的诗句是押韵的。从中挑选,求最多可以构成多少押韵句,并且输出这些句子在原序列中的位置。
Sample Input
15
1 2 3 1 2 1 2 3 3 2 1 1 3 2 2
3
1 2 3
Sample Output
3
1 2 4 5
7 8 9 10
11 12 14 15
0
分析:设dp[i]表示从 1 到 i 之间押韵句的最大数目,f(i,j)表示当[i,j]之间可以组出一句押韵句时为1,否则为0
则dp[i] = max{dp[i-1] , dp[j] + f(j+1,i)}
当(i,j)之间有2个数出现的次数大于等于2时,f(i,j)=1,这2个数可以相等,即1个数出现4次
路径打印课真是乱啊
代码如下:
1 # include<iostream> 2 # include<cstdio> 3 # include<vector> 4 # include<algorithm> 5 using namespace std; 6 const int N = 4005; 7 int data[N],ks[N]; 8 int n,kn; 9 int dp[N]; 10 vector<int> path[N]; //记录路径 11 vector<int> pos[N]; 12 int par[N]; //路径压缩 13 int out[N/4]; //输出路径 14 15 void solve() 16 { 17 if(n < 4) 18 { 19 printf("0\n\n"); 20 return ; 21 } 22 kn = n; 23 sort(ks,ks+kn); //原序列复制后排序 24 kn = unique(ks,ks+kn) - ks; //去重函数,返回相邻不重复的个数,即元素种类数 25 int i,j,k; 26 for(i=0; i<n; i++) 27 { 28 data[i] = lower_bound(ks,ks+kn,data[i]) - ks; 29 //lower_bound()返回一个 iterator 它指向在[first,last)标记的有序序列中可以插入value,而不会破坏容器顺序的第一个位置,而这个位置标记了一个大于等于value 的值。 30 } 31 for(i=0; i<=3; i++) 32 { 33 dp[i] = 0; 34 par[i] = -1; 35 } 36 vector<int >tmp; 37 for(i=3; i<n; i++) 38 { 39 dp[i+1] = dp[i]; 40 path[i+1] = path[i]; 41 par[i+1] = par[i]; 42 for(j=0; j<kn; j++) 43 pos[j].clear(); 44 tmp.clear(); 45 for(j=i; j>=0; j--) 46 { 47 k = data[j]; 48 pos[k].push_back(j+1); 49 if(pos[k].size()==2) 50 { 51 tmp.push_back(pos[k][0]); 52 tmp.push_back(pos[k][1]); 53 pos[k].clear(); 54 if(tmp.size()==4) break; 55 } 56 } 57 if(j >= 0) 58 { 59 if(dp[i+1] < dp[j]+1) 60 { 61 dp[i+1] = dp[j] + 1; 62 sort(tmp.begin(),tmp.end()); 63 path[i+1] = tmp; //同为vector类型,可赋值 64 par[i+1] = j; 65 } 66 } 67 } 68 printf("%d\n",dp[n]); 69 int u; 70 u =n; 71 for(i=dp[n]-1; i>=0; i--) 72 { 73 out[i] = u; 74 u= par[u]; 75 } 76 for(i=0; i<dp[n]; i++) 77 { 78 for(j=0; j<3; j++) 79 { 80 printf("%d ",path[out[i]][j]); 81 } 82 printf("%d\n",path[out[i]][j]); 83 } 84 puts(""); 85 } 86 87 int main() 88 { 89 while(scanf("%d",&n)!=EOF) 90 { 91 for(int i =0; i<n; i++) 92 { 93 scanf("%d",&data[i]); 94 ks[i] = data[i]; 95 } 96 solve(); 97 } 98 return 0; 99 }
把每一件简单的事情做好,就是不简单;把每一件平凡的事情做好,就是不平凡!相信自己,创造奇迹~~