标签:
http://acm.hdu.edu.cn/showproblem.php?pid=4381
1 5 2 2 3 3 1 3 3
Case 1: 3 1
/** hdu 4381 背包变形 题目大意:给定一个区间1~n,所有n个点都是黑色,操作:1 a b 把1~a区间内的b个点变成白色,2 a b 把a~n之间的b个点变成白色,若给定区间黑点数目 不足b个,则该操作不能执行,问最多能变成多少白色,若变成最多的白色那么最少的操作数是多少? 解题思路:我们把1~a操作的区间按a值递增排序,每次先涂最左边的,dp[j]表示用涂满前j个点的最少操作数,状态转移方程为:dp1[j]=min(dp1[j],dp1[j-p1[i].num]+1); a~n的区间做一个转换后和1~a一样操作。然后枚举涂的个数i即可,dp1[j]+dp2[i-j]<=m,有效。其中i:1~n,j:0~i */ #include <stdio.h> #include <algorithm> #include <iostream> #include <string.h> using namespace std; struct note { int x,num; bool operator < (const note &other)const { return x<other.x; } } p1[1005],p2[1005]; int n,m,dp1[1005],dp2[1005]; int main() { int T,tt=0; scanf("%d",&T); while(T--) { scanf("%d%d",&n,&m); int k1=0,k2=0; for(int i=0; i<m; i++) { int u,v,w; scanf("%d%d%d",&u,&v,&w); if(u==1) { p1[k1].x=v; p1[k1++].num=w; } else { p2[k2].x=n+1-v; p2[k2++].num=w; } } sort(p1,p1+k1); sort(p2,p2+k2); memset(dp1,0x3f3f3f,sizeof(dp1)); memset(dp2,0x3f3f3f,sizeof(dp2)); dp1[0]=dp2[0]=0; for(int i=0; i<k1; i++) { for(int j=p1[i].x; j>=p1[i].num; j--) { dp1[j]=min(dp1[j],dp1[j-p1[i].num]+1); } } for(int i=0; i<k2; i++) { for(int j=p2[i].x; j>=p2[i].num; j--) { dp2[j]=min(dp2[j],dp2[j-p2[i].num]+1); } } int tmp,ans=0,sum=0; for(int i=1;i<=n;i++) { for(int j=0;j<=i;j++) { tmp=dp1[j]+dp2[i-j]; if(tmp<=m) { if(ans!=i) { ans=i; sum=tmp; } else { sum=min(sum,tmp); } } } } printf("Case %d: %d %d\n",++tt,ans,sum); } return 0; }
标签:
原文地址:http://blog.csdn.net/lvshubao1314/article/details/43772983