题意是给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种,可以对篮子里的物品颜色用每个位来存储,所以就用到了位状态压缩;
Sample Input
5
1 2 3 4
1 5 6 7
2 3 3 3
4 9 8 6
8 7 2 1
Sample Output
8
这题少说也拍过5遍了,好题啊
1 #include<cstdio> 2 #include<iostream> 3 #include<algorithm> 4 #include<cstring> 5 #include<cmath> 6 #include<queue> 7 #include<map> 8 using namespace std; 9 #define MOD 1000000007 10 const int INF=0x3f3f3f3f; 11 const double eps=1e-5; 12 #define cl(a) memset(a,0,sizeof(a)) 13 #define ts printf("***** "); 14 const int MAXN=1005; 15 int n,m,tt; 16 int dp[45][45][45][45]; 17 int c[45][5]; 18 int x[5]; //x[i]表示第i堆的状态,并不是当前状态,而是取走的状态 19 int dfs(int b,int num) 20 { 21 if(dp[x[1]][x[2]][x[3]][x[4]]!=-1) return dp[x[1]][x[2]][x[3]][x[4]]; 22 int maxs=0,sum=0; 23 for(int i=1;i<=4;i++) 24 { 25 x[i]++; 26 if(x[i]<=n) 27 { 28 int bit=1<<(c[x[i]][i]); 29 if(b&bit) 30 { 31 sum=dfs(b&(~bit),num-1)+1; 32 } 33 else if(num<4) 34 { 35 sum=dfs(b|bit,num+1); 36 } 37 } 38 maxs=max(maxs,sum); 39 x[i]--; 40 } 41 return dp[x[1]][x[2]][x[3]][x[4]]=maxs; 42 } 43 int main() 44 { 45 int i,j,k; 46 #ifndef ONLINE_JUDGE 47 freopen("1.in","r",stdin); 48 #endif 49 while(scanf("%d",&n)!=EOF&&n!=0) 50 { 51 for(i=1;i<=n;i++) 52 { 53 for(j=1;j<=4;j++) 54 scanf("%d",&c[i][j]); 55 } 56 memset(dp,-1,sizeof(dp)); 57 x[1]=x[2]=x[3]=x[4]=0; 58 int ans=dfs(0,0); 59 printf("%d ",ans); 60 } 61 }