hdu1074(状压dp)

本文深入解析了状压动态规划(状压DP)的基本概念和核心思想,通过实例展示了如何利用二进制记录状态,枚举所有可能情况,实现从已知状态推导未知状态的过程。代码示例详细解释了如何计算在特定条件下完成任务所需的时间和代价,适用于算法竞赛和复杂问题求解。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

思路:

先说什么是状压dp(一开始我也不知道,但是做了一次之后发现还挺简单的),一句话概括就是一种很暴力的dp方式;

核心思想是:枚举所有的情况,用二进制记录状态

这道题其实只要枚举所有状态,并且是根据前面的状态推导得到,如:

用(111)表示三门课都完成,则这个状态有可能是从(110),(101),(011)这三种状态推出;

代码如下:

#include<cstdio>
#include<algorithm>

using namespace std;
#define inf 0x3f3f3f3f
struct node1
{
	char name[100];
	int  cost;
	int  dead;
}work[20];//每个任务
struct node2
{
	int fa;//父节点
	int reduce; //要扣的分数 
	int cost;//完成当前状态要的时间
	int nowbook;//当前状态比父状态多完成了哪一门课 
}dp[1<<16];//完成当前状态要扣的最少分数 
int n;
int main()
{
	int T;
	scanf("%d",&T);
	while(T--)
	{
		scanf("%d",&n);
		for(int i=0;i<n;i++)
		{
			scanf("%s%d%d",work[i].name,&work[i].dead,&work[i].cost);
		} 
		int end=1<<n;
		for(int i=1;i<end;i++)
		{
			dp[i].reduce=inf;
			for(int j=n-1;j>=0;j--)
			{
				int temp=1<<j;
				if(temp&i)//说明这个状态要完成的是j这门课 
				{
					int ttemp=i-temp;//代表上个状态
					int reduce=work[j].dead-dp[ttemp].cost-work[j].cost;//当前状态要扣的分数 
					reduce*=(-1);
					if(reduce<0)
					{
						reduce=0;
					}
					if(dp[ttemp].reduce+reduce<dp[i].reduce)
					{
						dp[i].fa=ttemp;
						dp[i].reduce=dp[ttemp].reduce+reduce;
						dp[i].nowbook=j;
						dp[i].cost=dp[ttemp].cost+work[j].cost;
					}
				}
			}
		}
		printf("%d\n",dp[end-1].reduce);
		int ans[100];
		int x=0;
		int t=end-1;
		while(t)
		{
			ans[x++]=dp[t].nowbook;
			t=dp[t].fa;
		}
		for(int i=x-1;i>=0;i--)
		{
			printf("%s\n",work[ans[i]].name);
		}
	
		
	}
	
	
	
	return 0;
} 

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值