题目链接:UVA - 10118
题目是PDF就不贴了,大意就是有四堆糖果,每堆有n个,有个人有个能盛五个糖的篮子,每次可以任选一堆糖,取最上面的那个放到篮子里,如果篮子里有两个颜色相同的,就可以把这两个放到口袋里,篮子满了并且没有相同糖果的时候游戏结束,求他最多能拿到的糖果数。这道题的状态是每堆分别拿num个时,口袋里最多能有多少个糖,dp[num1][num2][num3][num4],也就是第一堆拿num1个,第二堆拿num2个.....时口袋里的糖数,每次循环尝试拿第i堆糖果的第num个,递归求解,初始状态为0,0,0,0. 这道题时限3s,我跑了差不多2s = = ,看了一下别人的都是用数组记录某种糖是否在篮子里出现过,我是用的set,每次都需要插入删除,大概时间是差在这里了、
#include <cstdio>
#include <iostream>
#include <set>
#include <queue>
#include <cstring>
using namespace std;
const int maxn = 45;
int c[4][maxn],n,dp[maxn][maxn][maxn][maxn],num[4];
set<int > s;
int solve(set<int > s){
if(dp[num[0]][num[1]][num[2]][num[3]]!=-1) return dp[num[0]][num[1]][num[2]][num[3]];
if(s.size()==5) return dp[num[0]][num[1]][num[2]][num[3]]=0;
int ans=0;
for(int i=0;i<4;i++){
if(num[i]==n) continue;
num[i]++;
if(s.count(c[i][num[i]])){
s.erase(c[i][num[i]]);
ans=max(ans,solve(s)+1);
s.insert(c[i][num[i]]);
}
else {
s.insert(c[i][num[i]]);
ans=max(ans,solve(s));
s.erase(c[i][num[i]]);
}
num[i]--;
}
return dp[num[0]][num[1]][num[2]][num[3]]=ans;
}
int main() {
while(~scanf("%d",&n)&&n){
memset(dp,-1,sizeof(dp));
memset(num,0,sizeof(num));
s.clear();
for(int i=1;i<=n;i++)
for(int j=0;j<4;j++)
scanf("%d",&c[j][i]);
printf("%d\n",solve(s));
}
return 0;
}
吐个槽,DP对我来说感觉真的是,比其他的东西要难学的多。。= = 希望能在题目中有所收获,就像教主说的 至少混个脸熟不是,哇哈哈哈。加油加油