题目大意:有4堆糖果, 每堆糖果有n颗糖果,然后给出每颗糖果的类型1~20,然后只有取走当前堆的前面一颗糖果后才可以取后面的糖果, 然后小伙伴有一个篮子,篮子可以装5个糖果,如果篮子中的糖果存在相同类型的两个糖果,便可以将这两颗糖果算成一对放进腰包,问,小伙伴按什么样的方式取糖果可以取到最多的糖果。
解题思路:记忆化搜索,开一个四维数组记录当前4堆糖果取走相应个数后能拿到的最多对糖果数。
思路很简单,这也多亏了前一段时间坚持把小白的递归刷完。
#include <stdio.h>
#include <string.h>
#define max(a,b) (a)>(b)?(a):(b)
const int N = 50;
const int M = 5;
int n, g[N][M], dp[N][N][N][N];
void init() {
memset(dp, -1, sizeof(dp));
memset(g, 0, sizeof(g));
for (int i = 0; i < n; i++)
for (int j = 0; j < 4; j++)
scanf("%d", &g[i][j]);
}
int solve(int num[], int rec[], int cnt) {
int& ans = dp[num[0]][num[1]][num[2]][num[3]];
if (ans > -1) return ans;
ans = 0;
if (cnt == 5) return ans;
for (int i = 0; i < 4; i++) {
if (num[i] == n) continue;
int t = g[num[i]][i];
if (rec[t]) {
rec[t] = 0, num[i]++;
ans = max(ans, solve(num, rec, cnt - 1) + 1);
rec[t] = 1, num[i]--;
}
else {
rec[t] = 1, num[i]++;
ans = max(ans, solve(num, rec, cnt + 1));
rec[t] = 0, num[i]--;
}
}
return ans;
}
int main() {
while (scanf("%d", &n), n) {
init();
int num[M], rec[N];
memset(rec, 0, sizeof(rec));
memset(num, 0, sizeof(num));
printf("%d\n", solve(num, rec, 0));
}
return 0;
}