Hdu-6249 2017CCPC-Final G.Alice’s Stamps 动态规划

题面

题意:给你n个集合,每个集合有L到R这些种类的邮票,让你选择其中的K个集合,使得最后选择的邮票种类尽可能多,N,L,R都<=2000

题解:容易乱想到网络流,可是再细想一下就会发现处理不了这种模型的

        然后看数据范围,想到dp,定义状态f[i][j]表示前i个集合选j个的最多种类,

        我们发现这需要N^3,因为每次除了枚举i,j还要枚举一个q,来记录新的一个集合是从上次的哪一个集合拓展覆盖来的

        苦思不得其解,看全场都a了,终于在最后1h改了状态(打的当然是重现赛)

       我们发现L,R也只有2000啊,刚刚那种定义如果可行,L,R不就离散一下,没必要说这个了啊

       所以又定义f[i][j],表示1-i的种类,用了j个集合的最好方案,对于每个位置i,我们先预处理up数组,覆盖i的区间最右能延伸到哪里

       转移就是f[i][j+1]=max(f[i-1][j+1]f,[i][j+1])    if (up[i]) f[up[i]][j+1]=max (f[up[i]][j+1],f[i-1][j]+len);  len 就是等于up[i]-i+1;

     

 1 #include<bits/stdc++.h>
 2 #define N 2005 
 3 using namespace std;
 4 int f[N][N],up[N],T,t=1,n,m,k;
 5 int main()
 6 {
 7     cin>>T;
 8     while (T--)
 9     {
10         scanf("%d%d%d",&n,&m,&k);
11         memset(up,0,sizeof up);
12         memset(f,0,sizeof f);
13         for(int i=1,x,y;i<=m;i++)
14         {
15             scanf("%d%d",&x,&y);
16             for(int j=x;j<=y;j++) up[j]=max(up[j],y);
17         }
18         for(int i=1;i<=n;i++)
19             for(int j=0;j<k;j++)
20             {
21                 f[i][j+1]=max(f[i][j+1],f[i-1][j+1]);
22                 if (up[i]) f[up[i]][j+1]=max(f[up[i]][j+1],f[i-1][j]+up[i]-i+1);
23             }
24         printf("Case #%d: %d
",t++,f[n][k]);
25     }
26     return 0;
27 }
原文地址:https://www.cnblogs.com/qywhy/p/9764631.html