codeforces 413D 2048 (dp)

题意:

这是个2048游戏的简化版,只有一行,如果有两个位置的值相等那么就相加,知道不能加为止,题目给出n个数只有三种情况0、2、4, 0表示可以是2也可以是4。问给出的n个数中满足和大于k的方案数。

题解:

一眼看过去方程很快出来,看似很简单但是很难。因为有这样数据8422,2242222,这样的话中间有组个不能相加,那么要处理后面如果后面的加起来等于前面的于是又可以相加。看到这种数据的确想不到什么好办法。

大牛正解


#include<iostream>
#include<math.h>
#include<stdio.h>
#include<algorithm>
#include<string.h>
#include<vector>
#include<map>
using namespace std;
typedef long long ll;
const int oo=0x3f3f3f3f;
const ll OO=1LL<<61;
const ll MOD=1000000007;
const int maxn=2005;
const int maxm=2050;
ll dp[maxn][maxm][2];
int a[maxn];

int main()
{
    int n,k;
    while(scanf("%d %d",&n,&k)!=EOF)
    {
        memset(dp,0,sizeof dp);
        for(int i=1;i<=n;i++)
            scanf("%d",&a[i]);
        dp[0][0][0]=1;
        for(int i=1;i<=n;i++)
        {
            for(int j=0;j<maxm;j++)
            {
                int p;
                if(a[i]==0||a[i]==2)
                {
                    p=min(j+2,2048);
                    dp[i][p][0]=(dp[i][p][0]+dp[i-1][j][0]+MOD)%MOD;
                    dp[i][p][1]=(dp[i][p][1]+dp[i-1][j][1]+MOD)%MOD;
                }
                if(a[i]==0||a[i]==4)
                {
                    if(j%4)
                    {
                        if(j>=(1<<k))///这步非常关键!!
                            dp[i][4][1]=(dp[i][4][1]+dp[i-1][j][0]+MOD)%MOD;
                        else
                            dp[i][4][0]=(dp[i][4][0]+dp[i-1][j][0]+MOD)%MOD;
                        dp[i][4][1]=(dp[i][4][1]+dp[i-1][j][1]+MOD)%MOD;
                    }
                    else
                    {
                        p=min(j+4,2048);
                        dp[i][p][0]=(dp[i][p][0]+dp[i-1][j][0]+MOD)%MOD;
                        dp[i][p][1]=(dp[i][p][1]+dp[i-1][j][1]+MOD)%MOD;
                    }
                }
            }
        }
        ll ans=0;
        for(int i=0;i<maxm;i++)
        {
            ans=(ans+dp[n][i][1]+MOD)%MOD;
            if(i>=(1<<k))
                ans=(ans+dp[n][i][0]+MOD)%MOD;
        }
        cout<<ans<<endl;
    }
    return 0;
}
/**
0 2 2
1 0 100
1 2 0
3

*/



你可能感兴趣的:(codeforces 413D 2048 (dp))