以d[ i ][ j ][ k ][ p ] 对应每一堆取到第几个糖果
有一个地方需要声明的是以d[ i ][ j ][ k ][ p ] 对应每一堆取到第几个糖果,那么与该状态对应的篮子的状态一定只有一个,这是这样动态规划的原因;
#include <cstring>
#include <cstdio>
#include <vector>
#include <iostream>
#include <algorithm>
using namespace std;
const int maxn = 45;
int d[maxn][maxn][maxn][maxn];
int s,n;
int st[5][maxn];
bool vis[maxn][maxn][maxn][maxn];
int dp(int t[],int s,int bask[]){
if(vis[t[1]][t[2] ][t[3] ][t[4]]) return d[t[1]][t[2] ][t[3] ][t[4]];
vis[t[1]][t[2] ][t[3] ][t[4]] = true;
if(s==5) return d[t[1]][t[2] ][t[3] ][t[4]]=0;
int& ans = d[t[1]][t[2] ][t[3] ][t[4]];
ans=0;
for(int i=1;i<=4;i++){
if(t[i] <= n){
int nt[7];
int nbask[25];
memcpy(nt,t,sizeof(nt));
memcpy(nbask,bask,sizeof(nbask));
if(bask[st[i][t[i]]]){
nbask[st[i][t[i]]] = 0;
nt[i]+=1;
ans=max(ans,dp(nt,s-1,nbask)+1);
}
else {
nbask[st[i][t[i]]] = 1;
nt[i]+=1;
ans=max(ans,dp(nt,s+1,nbask));
}
}
}
return ans;
}
int main()
{
while(scanf("%d",&n)==1&&n){
for(int j=1;j<=n;j++)
for(int i=1;i<=4;i++)
scanf("%d",&st[i][j]);
int top[7],bask[25];
memset(bask,0,sizeof(bask));
memset(vis,false,sizeof(vis));
for(int i=1;i<=4;i++) top[i]=1;
printf("%d\n",dp(top,0,bask));
}
return 0;
}