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

来源:互联网 发布:c语言输出倒等腰三角形 编辑:程序博客网 时间:2024/05/22 08:28

题目的意思: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;}



1 0