UVA 10118 Free Candies

来源:互联网 发布:淘宝买家数据出售 qq 编辑:程序博客网 时间:2024/05/21 09:04

题目链接:http://acm.hust.edu.cn/vjudge/problem/19440


题意:一个人取四堆都为n的糖果,糖果的种类为1~20,他有一个可以最多装五颗糖的小篮子,如果篮子里有两颗一样的糖果,那么就可以把这一对糖果拿走。问最多可以得到多少对糖果。


思路:记忆化搜索dp[a][b][c][d]表示这四堆糖果分别取走了a,b,c,d个时得到的最大对数。对于dp[a][b][c][d]这个状态,枚举取糖果的堆,递归记忆化搜索取结果最大的情况。


#include <cstdio>#include <cmath>#include <cstring>#include <string>#include <cstdlib>#include <iostream>#include <algorithm>#include <stack>#include <map>#include <set>#include <vector>#include <sstream>#include <queue>#include <utility>using namespace std;#define rep(i,j,k) for (int i=j;i<=k;i++)#define Rrep(i,j,k) for (int i=j;i>=k;i--)#define Clean(x,y) memset(x,y,sizeof(x))#define LL long long#define ULL unsigned long long#define inf 0x7fffffff#define mod 100000007const int maxn = 42;int a[maxn][maxn];int dp[maxn][maxn][maxn][maxn];bool choose[30]; //每种糖果是否已经在篮子里了int n;int dfs( int pos[] , int num ){    int &ans = dp[pos[0]][pos[1]][pos[2]][pos[3]];    if( ans != -1 ) return ans;    if ( num == 5 ) return ans = 0; //篮子满了    ans = 0;    rep(i,0,3)    {        if ( pos[i] == n ) continue;//当前堆取完了        pos[i]++;        if ( choose[ a[pos[i]][i] ] ) //选过当前糖果        {            choose[ a[pos[i]][i]  ] = false;            ans = max( ans , dfs( pos , num - 1 ) + 1 ); //自己取到了一对糖果            choose[ a[pos[i]][i]  ] = true;        }        else //之前没选过        {            choose[ a[pos[i]][i]  ] = true;            ans = max( ans , dfs( pos , num + 1 ) );            choose[ a[pos[i]][i]  ] = false;        }        pos[i]--;    }    return ans;}int main(){    while( cin>>n )    {        if ( !n ) break;        rep(i,1,n)            rep(j,0,3) scanf("%d",&a[i][j]);        Clean(dp,-1);        Clean(choose,false);        int pos[4] = {0,0,0,0};        printf("%d\n",dfs(pos,0));    }    return 0;}


0 0