题意:有4堆糖果,每堆有n个,按顺序排列。每次可以拿某堆最上面的1个糖果放到一个中转的地方,如果中转的地方有两个一样颜色的糖果,就可以把同色的据为己有。中转的地方最多容纳5个糖果,满了之后游戏结束。问最多拿到几对糖果。
思路:DP。DP[i][j][k][l]。i,j,k,l表示第1,2,3,4堆。数组存的是中转糖的情况,为了节省空间,20种颜色转换为20位的二进制数,有该种颜色的糖就在对应位置1。
#include <iostream>
#include <stdio.h>
#include <cmath>
#include <algorithm>
#include <iomanip>
#include <cstdlib>
#include <string>
#include <memory.h>
#include <vector>
#include <queue>
#include <stack>
#include <ctype.h>
#define INF 1000000
using namespace std;
int P[5][50];
int n;
int DP[42][42][42][42];
int count(int i){
if(i==-1)return INF;
int re=0;
while(i!=0){
re+=i&1;
i=i>>1;
}
return re;
}
int main(){
while(cin>>n){
if(!n)break;
for(int i=1;i<=n;i++){
for(int j=1;j<=4;j++){
cin>>P[j][i];
}
}
int ans=0;
for(int i=0;i<=n;i++){
for(int j=0;j<=n;j++){
for(int k=0;k<=n;k++){
for(int l=0;l<=n;l++){
if( !(i||j||k||l) )continue;
bool flag=false;
if(l&&count(DP[i][j][k][l-1])<5){
DP[i][j][k][l]=DP[i][j][k][l-1]^(1<<(P[4][l]-1));
flag=true;
}
if(k&&count(DP[i][j][k-1][l])<5){
DP[i][j][k][l]=DP[i][j][k-1][l]^(1<<(P[3][k]-1));
flag=true;
}
if(j&&count(DP[i][j-1][k][l])<5){
DP[i][j][k][l]=DP[i][j-1][k][l]^(1<<(P[2][j]-1));
flag=true;
}
if(i&&count(DP[i-1][j][k][l])<5){
DP[i][j][k][l]=DP[i-1][j][k][l]^(1<<(P[1][i]-1));
flag=true;
}
if(!flag)DP[i][j][k][l]=-1;
if( (i+j+k+l-count(DP[i][j][k][l]))>ans)ans=i+j+k+l-count(DP[i][j][k][l]);
}
}
}
}
cout<<ans/2<<endl;
}
return 0;
}