题目:https://vjudge.net/problem/UVA-10118
思路:DP题
dp(p1, p2, p3, p4, st) 表示四堆糖果分别拿到p1, p2, p3, p4个的时候,剩余的糖果能被拿走几个,st表示当前篮子里的状态,可以用set< int >记录或者用二进制集合记录,那么状态转移方程就是dp(分别把每堆顶上的糖果放到篮子里的状态),如果篮子里有相同颜色就+1, 没有就不加,取可能决策的最大值。
代码:c++
#include <iostream>
#include <cstdio>
#include <cstring>
#include <string>
#include <map>
#include <vector>
#include <set>
#include <algorithm>
#include <queue>
#include <cmath>
using namespace std;
const int maxn = 42;
const int INF = 2147483647;
int n;
int candy[4][maxn];
int d[maxn][maxn][maxn][maxn];
bool vis[maxn][maxn][maxn][maxn];
int dp(int p1, int p2, int p3, int p4, set<int> st)
{
int &dcur = d[p1][p2][p3][p4];
bool &viscur = vis[p1][p2][p3][p4];
if (viscur)
{
return dcur;
}
dcur = 0;
if (st.size() == 5)
{
viscur = true;
return dcur = 0;
}
if (p1 != n)
{
set<int> t(st);
if (!t.count(candy[0][p1]))
{
t.insert(candy[0][p1]);
dcur = max(dcur, dp(p1 + 1, p2, p3, p4, t));
}
else
{
t.erase(candy[0][p1]);
dcur = max(dcur, dp(p1 + 1, p2, p3, p4, t) + 1);
}
}
if (p2 != n)
{
set<int> t(st);
if (!t.count(candy[1][p2]))
{
t.insert(candy[1][p2]);
dcur = max(dcur, dp(p1, p2 + 1, p3, p4, t));
}
else
{
t.erase(candy[1][p2]);
dcur = max(dcur, dp(p1, p2 + 1, p3, p4, t) + 1);
}
}
if (p3 != n)
{
set<int> t(st);
if (!t.count(candy[2][p3]))
{
t.insert(candy[2][p3]);
dcur = max(dcur, dp(p1, p2, p3 + 1, p4, t));
}
else
{
t.erase(candy[2][p3]);
dcur = max(dcur, dp(p1, p2, p3 + 1, p4, t) + 1);
}
}
if (p4 != n)
{
set<int> t(st);
if (!t.count(candy[3][p4]))
{
t.insert(candy[3][p4]);
dcur = max(dcur, dp(p1, p2, p3, p4 + 1, t));
}
else
{
t.erase(candy[3][p4]);
dcur = max(dcur, dp(p1, p2, p3, p4 + 1, t) + 1);
}
}
viscur = true;
return dcur;
}
int main()
{
while (scanf("%d", &n) && n)
{
for (int i = 0; i < n; i++)
{
for (int j = 0; j < 4; j++)
{
scanf("%d", &candy[j][i]);
}
}
memset(vis, 0, sizeof(vis));
cout << dp(0, 0, 0, 0, set<int>()) << endl;
}
return 0;
}