欢迎访问我的个人网站==》 jiashubing.cn

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 }

 

 

 

posted @ 2013-09-20 12:15  贾树丙  阅读(329)  评论(0编辑  收藏  举报