您的位置:首页 > 其它

hdu 1074 Doing Homework(记忆化搜索+状态压缩)

2013-11-16 18:02 363 查看
这道题被我拖很久了。

先是大概4月份的时候吧,看了一下。放弃了。

3,4天前有看了一下,当时去写了个n!的暴力,妥妥的T了。

然后注意到n的范围很小,肯定是压缩一下状态。

我艹,压缩什么?0和1不是表示有没有选吗?

想了几分钟,又放弃了。

然后碰巧最近写了几个记忆化搜索,我发现如果你递推不扎实的话

先练好搜索,然后写记忆化也一般没有什么大事。

然后也有看状压的pdf,但是似乎都是在一个棋盘上搞来搞去(我艹,无奈)。

今天早上起来时,忽然对这个题有些想法,当时大概的思路是

这样的。从0开始搜到整个序列都是1,还以为自己的程序是记忆化。

其实呢,很容易证明这个想法是错的,从不同顺序搜到整个序列都是1的答案

应该是一样的(好像没有表达清楚)。

那么正解是怎么搜呢?

应该从整个序列都是1搜到0。。。为什么?画个多叉树的图,感受一下。这样记忆化才有意义。

但是。。。。。。。。。

时间怎么搞呢?就是我们的边界怎么处理呢?很明显肯定是第一个就是边界。

但是我们保存哪个时间呢?

我又陷入无奈。。。。。

其实可以这样,你先把所有情况的时间都预处理出来(具体见代码)。

这样写,应该是最简单的。。。网上各种代码抄来抄去我也奉献一个新鲜的血液吧。。。

/*
author:ray007great
version:1.0
*/
#include<cstdio>
#include<algorithm>
#include<iostream>
#include<cstring>
#include<cstdlib>
#include<cmath>
#include<vector>
#include<set>
#include<string>
#include<queue>
using namespace std;
typedef long long ll;
/* define */

#define sf(a) scanf("%d",&a)
#define sfs(a) scanf("%s",a)
#define sfI(a) scanf("%I64d",&a)
#define pf(a) printf("%d\n",a)
#define pfI(a) printf("%I64d\n",a)
#define rep(i,a,b) for(int i=(a);i<=(b);i++)
#define repd(i,a,b) for(int i=(a);i>=(b);i--)
#define rep1(i,a,b) for(int i=(a);i<(b);i++)
#define clr(a) memset(a,0,sizeof(a))
#define clr1(a) memset(a,-1,sizeof(a))
#define pfk printf("fuck\n")

/* define */
const int inf = 9999999;
int son[1<<20],pa[1<<20];
struct node{
string name;
int dead,cost;
}work[250];
int dp[1<<20],n,Time[1<<20];
int dfs(int s){
if(~dp[s]) return dp[s];
//cout<<s<<endl;
int ans=inf,ts,res,pos;
for(int i=n-1;i>=0;i--){
///pfk;
//cout<<s<<endl;
if((s>>i)&1){
// pfk;
ts=s&~(1<<i);res=dfs(ts);
int dif=Time[ts]+work[i].cost-work[i].dead;
if(dif<=0 && res<ans){ans=res;pos=i;son[s]=ts;pa[s]=i;}
else if(dif>0 && res+dif<ans){ans=res+dif;pos=i;son[s]=ts;pa[s]=i;}
}
}
return dp[s]=ans;
}
int cnt;
void print(int x){
if(x==0) return ;
print(son[x]);
cout<<work[pa[x]].name<<endl;

}
void getTime(){
for(int s=0;s<1<<n;s++){
for(int j=0;j<n;j++){
if(s&(1<<j))
Time[s]+=work[j].cost;
}
}
}
int main(){
int t;
cin>>t;
while(t--){
cin>>n;
for(int i=0;i<n;i++)
cin>>work[i].name>>work[i].dead>>work[i].cost;
clr1(dp);clr(Time);cnt=0;dp[0]=0;
getTime();
cout<<dfs((1<<n)-1)<<endl;
print((1<<n)-1);
}
return 0;
}
/*
2
3
Computer 3 3
English 20 1
Math 3 2
*/
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签:  状态压缩