您的位置:首页 > 其它

状态压缩DP 不断学习中。。。。。。

2013-05-14 17:01 225 查看
HDU 3001 travelling:http://acm.hdu.edu.cn/showproblem.php?pid=3001

注意题目叙述: “But Mr Acmer gets bored so easily that he doesn't want to visit a city more than twice!”,

  题目大意:加限制的最小生成树,限制条件:每个节点最多只能到达两次, 用三进制(想想二进制表示的意思,可对比理解)

#include<iostream>
#include<cstdio>
#include<cstring>
#include<queue>

using namespace std;

const int N=1<<16;

struct node{
char name[110];
int dt,cost;
}work[30];

struct DP{
int time,cost,status;   //时间 罚分 完成状态
char s[30]; //记录顺序 课程的编号
}dp
; //下标表示状态 如dp[5] 化为 二进制 dp[101] 表示完成了编号 0 ,2的作业(从0开始)

int n;

void BFS(){
queue<DP> q;
while(!q.empty())
q.pop();
DP cur,next;
cur.time=0, cur.cost=0, cur.status=0, cur.s[0]='\0';
dp[0]=cur;
q.push(cur);
while(!q.empty()){
cur=q.front();
q.pop();
for(int i=0;i<n;i++){
if((cur.status&(1<<i))==0){ //没有含有第i门课程
next.status=cur.status | (1<<i);
next.time=cur.time+work[i].cost;
next.cost=cur.cost;
if(next.time>work[i].dt)
next.cost+=next.time-work[i].dt;
if(dp[next.status].cost==-1 || next.cost<dp[next.status].cost){ //更新
strcpy(next.s,cur.s);
int len=strlen(next.s);
next.s[len]=i+'0';
next.s[len+1]='\0'; //注意
dp[next.status]=next;
q.push(next);
}
}
}
}
}

int main(){

//freopen("input.txt","r",stdin);

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].dt,&work[i].cost);
memset(dp,0,sizeof(dp));
for(int i=0;i<(1<<n);i++)
dp[i].cost=-1;
BFS();
int M=(1<<n)-1;
printf("%d\n",dp[M].cost);
for(int i=0;i<n;i++)
printf("%s\n",work[dp[M].s[i]-'0'].name);
}
return 0;
}


View Code
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: