杭电ACM1074——Doing Homework~~状态压缩DP

题目的意思:N门课程有作业,一个时间是最迟交的时间,一个是需要耗费多少时间来完成,到了期限,迟交多少,就扣多少分,求扣最少分的做作业的顺序。

N小于等于15,可以枚举所以的情况,数的二进制来表示各种情况。

对于集合编码成整数,可以看我的另一篇博客:点击打开链接

枚举每一门课程,S & (1 << i)表示第i门课程是否完成,为 1 就是完成了。

对于状态压缩DP还不是很熟,特别是位运算,很是蛋疼。

参考别人博客学习的。

下面的是AC的代码:

#include <iostream>
#include <cstring>
#include <string>
#include <stack>
using namespace std;

const int INF = 100000000;

struct data
{
	string name;
	int last, cost;
}Data[20];

struct DP
{
	int time, score, pre, now;//time为该状态多出来的时间,score是扣的分,pre,now用来记录路径
}dp[1 << 15 + 1];


int main()
{
	int t, n, i, end;
	cin >> t;
	while(t--)
	{
		memset(dp, 0, sizeof(dp));//初始化
		cin >> n;                 //输入
		for(i = 0; i < n; i++)
			cin >> Data[i].name >> Data[i].last >> Data[i].cost;
		end = 1 << n;
		for(int S = 1; S < end; S++)//枚举所以的状态
		{
			dp[S].score = INF;
			for(i = n - 1; i >= 0; i--)  //每一门课程
			{
				int temp = 1 << i;
				if(S & temp)             //判断第i门课程是否完成
				{ 
					int a = S - temp;    //集合S去掉 i,也就是第i门课程没完成,也就是上一个状态
					int s = dp[a].time + Data[i].cost - Data[i].last;
					if(s < 0)
						s = 0;
					if(s + dp[a].score < dp[S].score)   //分数小于现在的状态
					{
						dp[S].score = s + dp[a].score;
						dp[S].pre = a;                   //记录路径
						dp[S].now = i;                   //记录路径
						dp[S].time = dp[a].time + Data[i].cost;
					}
				}
			}
		}
		stack <int>Stack;
		cout << dp[end - 1].score << endl;
		int res = end - 1;
		while(res)          //取路径
		{
			Stack.push(dp[res].now);
			res = dp[res].pre;
		}
		while(!Stack.empty())  //输出
		{
			cout << Data[Stack.top()].name << endl;
			Stack.pop();
		}
	}
	return 0;
}



  • 2
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值