题目的意思就是有四堆糖果.你每次可以取走每一堆顶部的糖果放在篮子里,篮子里最多只能放5个,如果里面有两个颜色一样的,就可以从篮子里拿走,带走.
输入第一行,是每堆有几个.然后给出糖果的颜色(数字)
问最多带走几 对 糖果.(两个一对)
f[i][j][k][l] 表示第一堆拿走了i 个,第二堆拿走了j个 ,第三堆拿走了k个 ,第四堆拿走了l个后,可以带走的糖果对数最多多少.
首先我们每次可以选择四个中的一个取.那么我可以循环遍历.
然后取完这个,我们开始判断,这个颜色是不是有了,有了,就篮子里数量减一,并把当前所在的堆已经拿走的糖果数量减一 ,继续递归 ,并且结果的拿走的对数加一.
如果颜色不一样,那么篮子里的数量加一,所在堆已经拿走的糖果数加一,
这个颜色是不是篮子里有了,可以用vis数组来标记.
当然我们还要回溯,把状态还原,来做下一次假设..
AC代码;
#include<stdio.h>
#include<string.h>
const int N = 45;
const int INF = 0x3f3f3f3f;
int pile[N][4];
int sta[4];
int f[N][N][N][N];
int vis[10];
int n;
int dp(int num) {
int &c = f[sta[0]][sta[1]][sta[2]][sta[3]];
if(c != -1)
return c;
if(num == 5)
return c = 0;
c = 0;
for (int i = 0 ; i < 4 ;i++) {
if(sta[i] == n)
continue;
int temp = pile[sta[i]][i];
if(vis[temp]) {
vis[temp] = 0;
sta[i]++;
int flag = dp(num - 1) + 1;
c = c > flag ? c : flag;
vis[temp] = 1;
}
else {
vis[temp] = 1;
sta[i]++;
int flag = dp(num + 1);
c = c > flag ? c : flag;
vis[temp] = 0;
}
sta[i]--;
}
return c;
}
int main () {
while(scanf("%d",&n) && n) {
memset(f, -1 ,sizeof(f));
memset(vis , 0 ,sizeof(vis));
memset(sta , 0 ,sizeof(sta));
for(int i = 0 ; i < n ;i++) {
for(int j = 0 ; j < 4 ;j++) {
scanf("%d",&pile[i][j]);
}
}
printf("%d\n" , dp(0));
}
}