uva 10118 动规

#include <bits/stdc++.h>
using namespace std;
const int maxn = 40 + 5;
int pile[4][maxn], dp[maxn][maxn][maxn][maxn], n, top[4];
#define REP(i,n) for(int i=0;i<(n);i++)
int DP(int cnt, int bit)
{
	int &ans = dp[top[0]][top[1]][top[2]][top[3]], mx = 0;
	if (ans != -1) return ans;
	if (cnt == 5) return ans = 0;
	REP(i, 4)
	{
		if (top[i] == n) continue;
		int color = pile[i][top[i]];
		bool flag = bit & (1 << color);
		bit ^= (1 << color); top[i]++;
		mx = max(mx, DP(cnt + (flag ? -1 : 1), bit) + flag);
		bit ^= (1 << color); top[i]--;
	}
	return ans = mx;
}
int main(int argc, char const *argv[])
{
	while (cin >> n && n)
	{
		REP(i, n) REP(j, 4) cin >> pile[j][i];
		memset(dp, -1, sizeof(dp));
		memset(top, 0, sizeof(top));
		cout << DP(0, 0) << endl;
	}
	return 0;
}


775bit 宇宙最短2333 运用了位运算

有4堆糖果,每堆有n(最多40)个,有一个篮子,最多装5个糖果,我们每次只能从某一堆糖果里拿出一个糖果,


题解来自于http://www.cnblogs.com/kedebug/archive/2013/04/07/3006493.html

如果篮子里有两个相同的糖果,那么就可以把这两个(一对)糖果放进自己的口袋里,问最多能拿走多少对糖果。糖果种类最多20种. 


(黑书 148 免费糖果)


思路:


1. 这一题有点逆向思维的味道,dp[a, b, c, d] 表示从每堆中分别拿 a, b, c, d 个时,最多能拿多少个糖果;


2. 注意一点:当拿到 a, b, c, d 时,不能再拿了,此时结果肯定就会固定。利用这一点性质,采用记忆化搜索能有效的减少重复子结构的计算;


3. 题目是只有 0 0 0 0 这一个出发点的,根据这个出发点进行深搜,最终得出结果。


4. 本题可谓是深搜 + 记忆化搜索的经典,状态不是那么明显,子结构也不是那么好抽象,因为转移的末状态并不是固定的,是在不断的搜索中求出来的;

你可能感兴趣的:(uva 10118 动规)