hdu 1074 doing homework
2017-07-23 15:40
302 查看
状态压缩dp
首先进行状态映射,(状态压缩),一共有15门课,每门课则可用一个数字位 来表示这门课作业是否已经做完,比如3门课 001,表示完成了第一门课作业,101,表示完成了第1门,第 3门作业。 则需要一个0-15位整数范围的数来表示所有状态
初始状态000, 结束状态1111…11 表示完成了所有作业。
再找状态转移方程
对于状态i, 这个状态可能由前一个状态pre,加上做完一道作业j得到。
也就是说对于所有状态i,和作业j,如果
状态转移方程:
由于需要记录完成顺序,且按字典序小的输出,开一个数组,pre[i]
来表示到达,i状态的需要完成的作业j
所以需要反向循环作业j,以此来保证字典序小的优先
核心代码
下面是几个参考博客:
http://www.cnblogs.com/neopenx/p/4048722.html
http://blog.csdn.net/acvay/article/details/48051975
下面是ac代码:
首先进行状态映射,(状态压缩),一共有15门课,每门课则可用一个数字位 来表示这门课作业是否已经做完,比如3门课 001,表示完成了第一门课作业,101,表示完成了第1门,第 3门作业。 则需要一个0-15位整数范围的数来表示所有状态
初始状态000, 结束状态1111…11 表示完成了所有作业。
再找状态转移方程
对于状态i, 这个状态可能由前一个状态pre,加上做完一道作业j得到。
也就是说对于所有状态i,和作业j,如果
(i &1<<j) ==0则表示状态i包含了完成了作业j, 通过
i^(1<<j)来得到前一个状态pre
状态转移方程:
dp[i]= min{dp[pre]+cost[j]} //pre is a set
由于需要记录完成顺序,且按字典序小的输出,开一个数组,pre[i]
来表示到达,i状态的需要完成的作业j
所以需要反向循环作业j,以此来保证字典序小的优先
核心代码
for(int i=1;i<m;i++{ for(int j=n-1;j>=0;j--) { int tmp=1<<j; if(!(i&tmp)) continue; int pre=i^tmp; if(dp[pre]+cost[j]<dp[i]){ //update dp[i] dp[i] =dp[pre]+cost[j]; Pre[i]=j; // the Pre is the array that for record; } } }
下面是几个参考博客:
http://www.cnblogs.com/neopenx/p/4048722.html
http://blog.csdn.net/acvay/article/details/48051975
下面是ac代码:
#include <iostream> #include<cstring> #include<string> #include<cstdio> #include<algorithm> #include<vector> using namespace std; #define MAX 105 #define INF 1000000 typedef struct Node{ char name[MAX]; int cost; int deadline; }Lesson; Lesson homework[20]; #define mx 1<<15 int dp[mx]; int p[mx]; int ti[mx]; void showTrace(int n){ if(p ==-1)return; showTrace(n^(1<<p )); cout<<homework[p ].name<<endl; } int main() { int t; scanf("%d",&t); int n=0; while(t--){ scanf("%d",&n); for(int i=0;i<n;i++){ scanf("%s%d%d",homework[i].name, &homework[i].deadline,&homework[i].cost); } memset(dp,1000000,sizeof(dp)); memset(p,-1,sizeof(p)); dp[0]=0; p[0]=-1; ti[0]=0; int m=1<<n; for(int i=1;i<m;i++){ for(int j=n-1;j>=0;j--){ int tmp=(1<<j); //whether is the i contains j if((i&tmp)==0) continue; // get the pre status which add j is i int pre=i^tmp; //pre is the status before j, // the i is the status contains j int reduce=ti[pre]+homework[j].cost-homework[j].deadline; reduce=reduce<0?0:reduce; // the status change function // dp[i]= min{dp[pre]+ cost[j]} // where pre is the status which add j is i if(dp[pre]+reduce<dp[i]){ dp[i]=dp[pre]+reduce; p[i]=j; ti[i]=ti[pre]+homework[j].cost; } } } printf("%d\n",dp[m-1]); showTrace(m-1); } return 0; }
相关文章推荐
- HDU 1074 Doing Homework(状压DP)
- hdu 1074 Doing Homework(状压DP)
- hdu 1074 Doing Homework(状压dp)
- hdu 1074 Doing Homework(记忆化搜索+状态压缩)
- hdu 1074 Doing Homework (状压dp)
- hdu 1074 Doing Homework(状压DP)
- HDU 1074 Doing Homework(状压DP+储存路径)
- hdu 1074 Doing Homework(状压DP)
- HDU 1074 Doing Homework(状压DP)
- HDU 1074 Doing Homework(状压DP+记录路径)
- hdu 1074 Doing Homework(状压DP)
- HDU 1074 Doing Homework
- HDU 1074 Doing Homework(状压DP)
- HDU - 1074 Doing Homework(状压dp)
- HDU 1074 Doing Homework(状压dp)
- HDU 1074 Doing Homework
- HDU 1074 Doing Homework(状压DP)
- HDU 1074 Doing Homework(状压DP)
- hdu 1074 Doing Homework(状压DP)
- hdu 1074 Doing Homework(状压dp)