http://acm.hdu.edu.cn/showproblem.php?pid=6249
题意:
给出n个区间,求选k个区间的最大区间并。
思路:
可能存在左端点相同的多个区间,那么此时我们肯定选右端点最大的那个区间。现在将区间按左端点排序,d[i][j]表示在1~i坐标轴范围内选择j个区间的最大区间并。
状态转移方程如下:
dp[i+1][j] = max(dp[i][j],dp[i+1][j]); //不选的话就和上一个一样 dp[i+num][j+1] = max(dp[i][j]+num,dp[i+num][j+1]); //选择
1 #include<iostream> 2 #include<cstdio> 3 #include<cstring> 4 #include<algorithm> 5 #include<queue> 6 using namespace std; 7 const int maxn = 2000+5; 8 9 int n,m,k; 10 int dp[maxn][maxn]; 11 12 struct node 13 { 14 int l,r; 15 bool operator< (const node& rhs) const 16 { 17 return l<rhs.l; 18 } 19 }s[maxn]; 20 21 int main() 22 { 23 //freopen("in.txt","r",stdin); 24 int T; 25 int kase = 0; 26 scanf("%d",&T); 27 while(T--) 28 { 29 scanf("%d%d%d",&n,&m,&k); 30 for(int i=1;i<=m;i++) 31 scanf("%d%d",&s[i].l,&s[i].r); 32 memset(dp,0,sizeof(dp)); 33 sort(s+1,s+m+1); 34 int pos = 1, num = 0; 35 for(int i=0;i<n;i++) 36 { 37 while(pos<=m && s[pos].l==i+1) 38 { 39 num = max(num, s[pos].r - s[pos].l + 1); 40 pos++; 41 } 42 43 for(int j=0;j<=k;j++) 44 { 45 dp[i+1][j] = max(dp[i][j],dp[i+1][j]); 46 dp[i+num][j+1] = max(dp[i][j]+num,dp[i+num][j+1]); 47 } 48 if(num) num--; //因为左端点右移了一位,所以这里需要 49 } 50 printf("Case #%d: ",++kase); 51 printf("%d\n",dp[n][k]); 52 } 53 return 0; 54 }