1068 乌龟棋



http://codevs.cn/problem/1068/

我的做法是用四维数组dp[50][50][50][50],dp[a][b][c][d]记录的是当剩下a个一的卡片,b个二的卡片,c个三的卡片,d个四的卡片时,最大的得分。

用vector维护到达每个点时的所有状态,所以我这个做法是完全暴力的做法优化而来的。看代码

#include<bits/stdc++.h>
#define  pb push_back
using namespace std;
const int maxn = 350;
struct node
{
    int a,b,c,d;
    int ans;
}ok;
vector<node>V[maxn];
int s[maxn],b[5],dp[40][40][40][40];
int main()
{
    int n,m;
    while(scanf("%d%d",&n,&m)!=EOF)
    {
        for(int i=0;i<n;i++) V[i].clear();
        for(int i=0;i<n;i++) scanf("%d",&s[i]);
        memset(b,0,sizeof(b));
        for(int i=1;i<=m;i++)
        {
            scanf("%d",&b[0]);
            b[b[0]]++;
        }
        memset(dp,-1,sizeof(dp));
        ok.ans = s[0],ok.a = b[1],ok.b = b[2],ok.c = b[3],ok.d = b[4];
        V[0].pb(ok);
        dp[b[1]][b[2]][b[3]][b[4]] = s[0];
        for(int i=1;i<n;i++)
        {
            for(int j=1;j<=4 && i-j>=0;j++)
            {
                for(int k=0;k<V[i-j].size();k++)
                {
                    ok = V[i-j][k];
                    if(j==1 && ok.a<=0 ) continue;
                    if(j==2 && ok.b<=0 ) continue;
                    if(j==3 && ok.c<=0 ) continue;
                    if(j==4 && ok.d<=0 ) continue;
                    if(dp[ok.a][ok.b][ok.c][ok.d]<=ok.ans)
                    {
                        switch(j)
                        {
                            case 1:ok.a--;break;
                            case 2:ok.b--;break;
                            case 3:ok.c--;break;
                            case 4:ok.d--;break;
                        }
                        ok.ans+=s[i];
                        if(dp[ok.a][ok.b][ok.c][ok.d]<ok.ans)
                        {
                            V[i].pb(ok);
                            dp[ok.a][ok.b][ok.c][ok.d]=ok.ans;
                        }
                    }
                }
            }
        }
       printf("%d\n",dp[0][0][0][0]);
    }
    return 0;
}
后来知道网上有种非常暴力的,直接枚举所有a,b,c,d四种卡片,那种做法比我的快多了。 我怎么就没想到呢!!!!

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值