hdu 1514(记忆化+位压缩+dp)

题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=1514

思路:orz...大牛讲的太妙了:

题意是给4堆(堆的高度小于等于40)有颜色(颜色的种类小于等于20)的物品,你有一个篮子最多能装5件物品,每次从这4堆物品里面
任取一件物品放进篮子里,但是取每堆物品时,必须先取上面的物品,才能取下面的物品,如果发现篮子里
的两种物品的颜色一样,那么把这两种物品拿出来,问最后最多能拿出多少对物品?;

解题思路:记忆化搜索+dp+状态压缩;

因为40×40×40×40不会太大,所以可以用dp[x[1]][x[2]][x[3]][x[4]]记录搜索的状态;

dp[x[1]][x[2]][x[3]][x[4]]记录4堆分别从x[1],x[2],x[3],x[4]处往下取所获得的最大值;

因为颜色种类最多20种,可以对篮子里的物品颜色用每个位来存储,所以就用到了位状态压缩;

最后就是一步一步的试探搜索了。。。

View Code
 1 #include<iostream>
 2 #include<cstring>
 3 #include<cstdio>
 4 using namespace std;
 5 int dp[45][45][45][45];
 6 int map[45][5];
 7 int x[5];
 8 int n;
 9 
10 int dfs(int basket,int num){
11     if(dp[x[1]][x[2]][x[3]][x[4]]!=-1){
12         return dp[x[1]][x[2]][x[3]][x[4]];
13     }
14     int sum=0,MAX=0,bit;
15     for(int i=1;i<=4;i++){
16         x[i]++;
17         if(x[i]<=n){
18             bit=(1<<map[x[i]][i]);
19             if(basket&bit){
20                 sum=dfs(basket&(~bit),num-1)+1;
21             }else if(num<4){
22                 sum=dfs(basket|bit,num+1);
23             }
24         }
25         if(sum>MAX)MAX=sum;
26         x[i]--;
27     }
28     return dp[x[1]][x[2]][x[3]][x[4]]=MAX;
29 }
30 
31 
32 
33 int main(){
34     while(~scanf("%d",&n)&&n){
35         for(int i=1;i<=n;i++)
36             for(int j=1;j<=4;j++)
37                 scanf("%d",&map[i][j]);
38         memset(dp,-1,sizeof(dp));
39         x[1]=x[2]=x[3]=x[4]=0;
40         int ans=dfs(0,0);
41         printf("%d\n",ans);
42     }
43     return 0;
44 }
45 
46 
47         

 

posted @ 2013-05-11 23:51  ihge2k  阅读(326)  评论(0编辑  收藏  举报