标签:
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