链接:https://vjudge.net/problem/UVA-10118
题意:
给你四个柱子,每个柱子有n个不同颜色的糖果。
每次只能取柱子顶的一个糖果。
手上最多抓5个糖果。但是手上每有2个相同的的糖果的时候可以将这一对糖果放到口袋。
求最多能放几对糖果到口袋。
思路:
记忆化搜索。dp。
dp[a][b][c][d]记录第一个柱子取a个,第二个柱子取b个。。。。的能得到的最大的对数。
Vis记录手上糖果颜色拥有的情况
代码:
#include <iostream>
#include <memory.h>
#include <vector>
#include <map>
#include <algorithm>
#include <cstdio>
#include <math.h>
#include <queue>
#include <string>
#include <stack>
#include <iterator>
#include <stdlib.h>
#include <time.h>
#include <assert.h>
using namespace std;
typedef long long LL;
const int MAXN = 40 + 10;
int n;
int dp[MAXN][MAXN][MAXN][MAXN];
int a[7][MAXN];
bool Vis[25];
int use[10];
int Dfs(int step)
{
if (dp[use[1]][use[2]][use[3]][use[4]] != -1) //当某种情况存在过之后就直接记录返回
return dp[use[1]][use[2]][use[3]][use[4]];
int res = 0;
if (step == 5)
return res;
for (int i = 1; i <= 4; i++)
{
int tmp = 0;
++use[i];
if (use[i] > n)
{
--use[i];
continue;
}
if (Vis[a[i][use[i]]])
{
Vis[a[i][use[i]]] = false;
tmp = Dfs(step - 1) + 1;
Vis[a[i][use[i]]] = true;
}
else
{
Vis[a[i][use[i]]] = true;
tmp = Dfs(step + 1);
Vis[a[i][use[i]]] = false;
}
--use[i];
res = max(res, tmp);
}
return dp[use[1]][use[2]][use[3]][use[4]] = res;
}
int main()
{
while (cin >> n && n)
{
memset(dp, -1, sizeof(dp));
memset(use, 0, sizeof(use));
memset(Vis, false, sizeof(Vis));
for (int i = 1;i <= n;i++)
{
for (int j = 1;j <= 4;j++)
{
cin >> a[j][i];
}
}
cout << Dfs(0) << endl;
}
return 0;
}
/*
3
1 2 3 4
5 6 7 8
1 2 3 4
*/