P1541 乌龟棋 题解(洛谷,动态规划递推)

题目:P1541 乌龟棋

感谢大神的题解(他的写的特别好)

写一下我对他的代码的理解吧(哎,蒟蒻就这能这样...)

代码:

#include<bits/stdc++.h>
#define ll long long
using namespace std;
ll num[350+100];
ll p[5];
ll f[41][41][41][41];
int main()
{
    ios::sync_with_stdio(false);
    ll n,m;//n格子数,m牌数
    cin>>n>>m;
    for(ll i=1;i<=n;i++)
        cin>>num[i];
    ll x;
    for(ll i=1;i<=m;i++)
        cin>>x,p[x]++;//偷懒用逗号隔开

    f[0][0][0][0]=num[1];
    for(ll a=0;a<=p[1];a++)
        for(ll b=0;b<=p[2];b++)
            for(ll c=0;c<=p[3];c++)
                for(ll d=0;d<=p[4];d++)
                {
                    ll r=1+1*a+2*b+3*c+4*d;
                    if(a>=1) f[a][b][c][d]=max(f[a][b][c][d],f[a-1][b][c][d]+num[r]);//如果有牌出
                    if(b>=1) f[a][b][c][d]=max(f[a][b][c][d],f[a][b-1][c][d]+num[r]);
                    if(c>=1) f[a][b][c][d]=max(f[a][b][c][d],f[a][b][c-1][d]+num[r]);
                    if(d>=1) f[a][b][c][d]=max(f[a][b][c][d],f[a][b][c][d-1]+num[r]);
                }
    cout<<f[p[1]][p[2]][p[3]][p[4]]<<endl;
}
点击加号展开代码

思路:

每个牌有四种,建立一个四维数组f[a][b][c][d]表示当现在使用了a张走一位牌,b...,c...,d张走四位牌后能获得的最大数字

然后输入数据的时候准备一个数组p[5],把a,b,c,d牌数量分别放入1,2,3,4位

 

然后

for(a=0~p[1])
   for(b=0~p[2])
    for(b=0~p[3])
      for(b=0~p[4])//表示遍历a,b,c,d全部情况,我们要的是答案f[p[1]][p[2]][p[3]][p[4]]

所以要想办法递推到f[p[1]][p[2]][p[3]][p[4]]

用4个max,计算每一次的最大f[a][b][c][d],

那个递推式中:

ll r=1+1*a+2*b+3*c+4*d;//r表示当前的位置,+1是,比如说a=b=c=d=0,但是他是在第一位,所以初始位是1
if(a>=1) f[a][b][c][d]=max(f[a][b][c][d],f[a-1][b][c][d]+num[r]);//如果有牌出
if(b>=1) f[a][b][c][d]=max(f[a][b][c][d],f[a][b-1][c][d]+num[r]);
if(c>=1) f[a][b][c][d]=max(f[a][b][c][d],f[a][b][c-1][d]+num[r]);
if(d>=1) f[a][b][c][d]=max(f[a][b][c][d],f[a][b][c][d-1]+num[r]);

中,a>=1是判断是否可以出牌

 

对于f[a-1][b][c][d]+num[r]的意思就是如果更新出了a牌之后的的数字总数,f[a][b][c][d]就是不出牌的数字总数,其实就是不变

 

posted @ 2018-11-18 09:59  ZYacmer  阅读(232)  评论(0编辑  收藏  举报