您的位置:首页 > 其它

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,如果
(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;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: