解题思路:多阶段dp,每次可以选择从四堆糖顶部拿出一颗。用dp[][][][]记录所有状态,那么如何处理状态的转换呢。这里用了非常巧妙的方法。定义一个一维数组top[5]记录四堆糖顶部的位置,动态规划时取了该位置的糖则top[i]++,递归返回则top[i]--。处理方式非常类似回溯法。用mark数组记录口袋里的颜色,处理用top数组,类似回溯法,具体实现方式可参见代码。
题目大意:有四堆糖,每次从堆顶拿出一个放篮子里,篮子里如果有相同颜色的糖果则把他们拿出放在自己口袋里。如果篮子满了且里面没有相同颜色的糖果,游戏结束,口袋里的糖果归他,问最多可以拿多少糖。
Sample Input
5
1 2 3 4
1 5 6 7
2 3 3 3
4 9 8 6
8 7 2 1
1
1 2 3 4
3
1 2 3 4
5 6 7 8
1 2 3 4
0
Sample Output
8
0
3
#include<cstdio>
#include<iostream>
#include<algorithm>
#include<cstring>
using namespace std;
int n, a[50][5], dp[50][50][50][50],top[5];
bool mark[100];
int f(int x) //这里递归函数的参数比较特殊,使用口袋里的糖果个数
{
int &ans = dp[top[1]][top[2]][top[3]][top[4]];
if (ans != -1) return ans;
if (x == 5) return ans; //返回