`
java-mans
  • 浏览: 11414134 次
文章分类
社区版块
存档分类
最新评论

HDU-1074-Doing Homework

 
阅读更多

HDU-1074-Doing Homework

http://acm.hdu.edu.cn/showproblem.php?pid=1074

状态压缩DP,我们可以使用一个二进制的数来表示做作业的状态,1表示做了,0表示没做

dp[i]表示状态i损失的分数,再做一个作业x可到另一状态dp[j],则要有i&x==0,若要有dp[a],dp[b]均可以到达dp[j],那么选择损失分数最小的,若分数相同,按题意的字典序,即选择a和b中较小的一个,因为题目的课程是按字典序给出的。

#include<iostream>
#include<cstdio>
#include<cstring>
#include<cstdlib>
using namespace std;
const int Max=1<<16;
struct node
{
	int time; //该状态的时间
	int pre; //前一状态
	int cost; //最小的损失
}dp[Max];
struct course
{
	int deadtime; //截止日期
	int cost; //所需时间
	char name[201];
}course[16];
int visit[Max];
void print(int status)
{
	int cur,num;
	cur=dp[status].pre^status; //刚做的课程
	num=0;
	cur>>=1;
	while(cur)
	{
		num++;
		cur>>=1;
	}
	if(dp[status].pre!=0)
	print(dp[status].pre);
	printf("%s\n",course[num].name);
}
int main()
{
	int i,n,t;
	int upper,work,cur,k,reduce;
	scanf("%d",&t);
	while(t--)
	{
		scanf("%d",&n);
		upper=(1<<n)-1;//最大的状态
		for(i=0;i<n;i++)
		scanf("%s%d%d",&course[i].name,&course[i].deadtime,&course[i].cost);
		memset(visit,0,sizeof(visit));
		dp[0].time=0;  //初始化
		dp[0].pre=-1;
		dp[0].cost=0;
		visit[0]=1;
		for(i=0;i<upper;i++)
		{
			for(work=0;work<n;work++)
			{
				cur=1<<work;
				if((cur&i)==0)  //该项课程还未做
				{
					k=cur|i;//下一状态
					dp[k].time=dp[i].time+course[work].cost;
					reduce=dp[k].time-course[work].deadtime;
					if(reduce<0)
					reduce=0;
					reduce+=dp[i].cost;
					if(visit[k]) //该状态已标记 
					{
						if(reduce<dp[k].cost)
						{
							dp[k].cost=reduce;
							dp[k].pre=i;
						}
						else if(reduce==dp[k].cost)
						{
							if(dp[k].pre>i)
							dp[k].pre=i;
						}
					}
					else
					{
						visit[k]=1;
						dp[k].cost=reduce;
						dp[k].pre=i;
					}
				}
			}
		}
		printf("%d\n",dp[upper].cost);
		print(upper);//递归输出 
	}
	return 0;
}


分享到:
评论

相关推荐

Global site tag (gtag.js) - Google Analytics