码迷,mamicode.com
首页 > 其他好文 > 详细

LianLianKan HDU - 4272(状压dp)

时间:2020-02-25 23:10:17      阅读:60      评论:0      收藏:0      [点我收藏+]

标签:cout   cin   状压   name   nbsp   思路   开始   main   namespace   

题意:就是连连看,有两个相同的就能消除,再加上两个特别的规定,一是只能从栈顶开始消除,而是两个相同的元素之间距离不能超过6,询问能否消除序列中所有元素。

思路:数据水,贪心就能过,但严谨的考虑,贪心显然不能解决所有问题。这题虽然序列很长,但是状态并不复杂,可以使用滚动的状压dp,然后考虑使用多少位表示状态,每一种状态表示第i位为栈首的序列状态,该位前最多能消除掉该位后四位,所以我们只需要表示后9位的状态即可,总计10位。

某位上1表示该位已被消除,0表示未被消除。

dp[i][j]表示从i位开始的10位,能否达到j状态。

#include <cstdio>
#include <iostream>
#include <cstring>

using namespace std;

const int maxn=1e3+10;
const int up=1<<10;
const int bit=9;

int dp[maxn][up];
int a[maxn];
int n;

int main()
{
    while(cin>>n)
    {
        for(int i=n;i>=1;i--) scanf("%d",a+i);
        memset(dp,0,sizeof(dp));

        dp[0][0]=1;
        for(int i=1;i<=n;i++)
        {
            for(int j=0;j<up;j++)
            {
                if(!dp[i-1][j]) continue;//该状态不存在,跳过

                if(j&1) dp[i][j>>1]=1;//该位已经消除
                else{
                    int cnt=0;//表示序列中已经被消除的数
                    for(int k=1;k<=bit;k++)
                    {
                        if(!((j>>k)&1)&&k-cnt<=5&&i+k<=n&&a[i]==a[i+k])
                        {
                            dp[i][j>>1|(1<<k-1)]=1;
                        }
                        else if((j>>k)&1) cnt++;
                    }
                }

            }
        }

        if(dp[n][0]) cout<<1<<endl;
        else cout<<0<<endl;
    }
}

 

LianLianKan HDU - 4272(状压dp)

标签:cout   cin   状压   name   nbsp   思路   开始   main   namespace   

原文地址:https://www.cnblogs.com/npunch/p/12364312.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!