UVA - 10118 Free Candies(dp)

题意:有4堆糖果,每堆有n个,现在又一个篮子,最多能装5个糖果,每次可以选一堆,拿顶部的糖果放到篮子中,如果篮子中有两个颜色相同的糖果,那么就可以放入口袋中,问最多能拿多少糖果。

思路:刚开始没仔细看题,以为放在篮子中的是有序的,只有相邻的才能拿走,想了好久都没想出来Orz……以后不能随便yy题意了。。。可以随意拿那么就好搞多了,因为知道了已经拿走的糖果就可以算出来有哪些糖果在篮子中,因为糖果肯定是一一配对的,没有办法和其他糖果配对的肯定在篮子中,每次有两种选择:选一个糖果和篮子中的消除,或者选一个糖果放到篮子中。


代码:


#include<iostream>
#include<cstdio>
#include<cstring>
#include<string>
#include<algorithm>
#include<map>
#include<queue>
#include<stack>
#include<set>
#include<cmath>
#include<vector>
#define inf 0x3f3f3f3f
#define Inf 0x3FFFFFFFFFFFFFFFLL
#define eps 1e-8
#define pi acos(-1.0)
using namespace std;
typedef long long ll;
const int maxn = 41;
int dp[maxn][maxn][maxn][maxn],n;
int color[4][maxn],sum[4][maxn][maxn];
int cnt[22],remain;
int f(int a,int b,int c,int d)
{
    if(a == n && b == n && c == n && d == n) return 0;
    if(dp[a][b][c][d] != -1) return dp[a][b][c][d];
    int & ans = dp[a][b][c][d] = 0;
    if(remain >= 5) return ans = 0;
    if(a < n)
    {
        if(cnt[color[0][a+1]] & 1)
        {
            cnt[color[0][a+1]]++;
            remain--;
            ans = max(ans,f(a+1,b,c,d) + 1);
            cnt[color[0][a+1]]--;
            remain++;
        }
        else
        {
            cnt[color[0][a+1]]++;
            remain++;
            ans = max(ans,f(a+1,b,c,d));
            cnt[color[0][a+1]]--;
            remain--;
        }
    }
    if(b < n)
    {
        if(cnt[color[1][b+1]] & 1)
        {
            cnt[color[1][b+1]]++;
            remain--;
            ans = max(ans,f(a,b+1,c,d) + 1);
            cnt[color[1][b+1]]--;
            remain++;
        }
        else
        {
            cnt[color[1][b+1]]++;
            remain++;
            ans = max(ans,f(a,b+1,c,d));
            cnt[color[1][b+1]]--;
            remain--;
        }
    }
    if(c < n)
    {
        if(cnt[color[2][c+1]] & 1)
        {
            cnt[color[2][c+1]]++;
            remain--;
            ans = max(ans,f(a,b,c+1,d) + 1);
            cnt[color[2][c+1]]--;
            remain++;
        }
        else
        {
            cnt[color[2][c+1]]++;
            remain++;
            ans = max(ans,f(a,b,c+1,d));
            cnt[color[2][c+1]]--;
            remain--;
        }
    }
    if(d < n)
    {
        if(cnt[color[3][d+1]] & 1)
        {
            cnt[color[3][d+1]]++;
            remain--;
            ans = max(ans,f(a,b,c,d+1) + 1);
            cnt[color[3][d+1]]--;
            remain++;
        }
        else
        {
            cnt[color[3][d+1]]++;
            remain++;
            ans = max(ans,f(a,b,c,d+1));
            cnt[color[3][d+1]]--;
            remain--;
        }
    }
    return ans;
}
int main()
{
//    freopen("in.txt","r",stdin);
//    freopen("out.txt","w",stdout);
    while(~scanf("%d",&n))
    {
        if(n == 0) break;
        memset(sum,0,sizeof(sum));
        memset(dp,0xff,sizeof(dp));
        for(int i = 1;i <= n;++i)
            for(int j = 0;j < 4;++j)
            {
                scanf("%d",&color[j][i]);
                sum[j][i][color[j][i]] = 1;
            }
        for(int i = 0;i < 4;++i)
            for(int j = 1;j <= n;++j)
                for(int k = 1;k <= 20;++k)
                    sum[i][j][k] += sum[i][j-1][k];
        memset(cnt,0,sizeof(cnt));
        remain = 0;
        int ans = f(0,0,0,0);
        printf("%d\n",ans);
    }
    return 0;
}


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值