HDU 2280 Tetris Comes Back

状态压缩,$dp$,预处理。

设$dp[i][j]$为前$i-1$行填满,第$i$行为状态$j$的最小需要$1$种类的数量。预处理好每种状态能推出哪些状态,并且记录下所需花费就可以了。

#pragma comment(linker, "/STACK:1024000000,1024000000")
#include<cstdio>
#include<cstring>
#include<cmath>
#include<algorithm>
#include<vector>
#include<map>
#include<set>
#include<queue>
#include<stack>
#include<iostream>
using namespace std;
typedef long long LL;
const double pi=acos(-1.0),eps=1e-6;
void File()
{
    freopen("D:\\in.txt","r",stdin);
    freopen("D:\\out.txt","w",stdout);
}
template <class T>
inline void read(T &x)
{
    char c = getchar();
    x = 0;
    while(!isdigit(c)) c = getchar();
    while(isdigit(c)) { x = x * 10 + c - '0'; c = getchar(); }
}

struct X
{
    int nx,cost;
}q[100000];
int n,c,cnt;
vector<int>v[40];
char s[1010][10];
int st[1010];
int dp[1005][35];

int check(int s,int pos)
{
    if(s&(1<<pos)) return 1;
    return 0;
}

void dfs(int S,int no,int p,int nx,int co)
{
    if(p==5)
    {
        q[cnt].nx=nx; q[cnt].cost=co;
        v[S].push_back(cnt); cnt++;
        return ;
    }

    if(check(no,p))
        dfs(S,no,p+1,nx,co);

    //1
    if(check(no,p)==0)
        dfs(S,no+(1<<p),p+1,nx,co+1);

    //2
    if(p>0&&check(no,p)==0&&check(nx,p)==0&&check(nx,p-1)==0)
        dfs(S,no+(1<<p),p+1,nx+(1<<p)+(1<<(p-1)),co);
    //3
    if(p+1<=4&&check(no,p)==0&&check(no,p+1)==0&&check(nx,p)==0&&check(nx,p+1)==0)
        dfs(S,no+(1<<p)+(1<<(p+1)),p+2,nx+(1<<p)+(1<<(p+1)),co);

    //4
    if(p+1<=4&&check(no,p)==0&&check(no,p+1)==0)
        dfs(S,no+(1<<p)+(1<<(p+1)),p+2,nx,co);

    //5
    if(check(no,p)==0&&check(nx,p)==0)
        dfs(S,no+(1<<p),p+1,nx+(1<<p),co);

    //6
    if(p+1<=4&&check(no,p)==0&&check(nx,p)==0&&check(nx,p+1)==0)
        dfs(S,no+(1<<p),p+1,nx+(1<<p)+(1<<(p+1)),co);

    //7
    if(p+1<=4&&check(no,p)==0&&check(no,p+1)==0&&check(nx,p+1)==0)
        dfs(S,no+(1<<p)+(1<<(p+1)),p+2,nx+(1<<(p+1)),co);

    //8
    if(p+1<=4&&check(no,p)==0&&check(no,p+1)==0&&check(nx,p)==0)
        dfs(S,no+(1<<p)+(1<<(p+1)),p+2,nx+(1<<p),co);
}

void init()
{
    cnt=0;
    for(int i=0;i<(1<<5);i++) dfs(i,i,0,0,0);
}

int main()
{
    init();

    while(~scanf("%d%d",&n,&c))
    {
        for(int i=0;i<n;i++) scanf("%s",s[i]);
        for(int i=0;i<n;i++)
        {
            st[i]=0;
            for(int j=0;j<5;j++)
            {
                int x=s[i][j]-'0';
                st[i]=st[i]+x*(1<<j);
            }
        }

        st[n]=0;

        memset(dp,-1,sizeof dp);

        dp[0][st[0]]=0;

        for(int i=0;i<n;i++)
        {
            for(int j=0;j<32;j++)
            {
                if(dp[i][j]==-1) continue;
                //printf("********\n");
                for(int t=0;t<v[j].size();t++)
                {
                    int id=v[j][t];
                    if(c-dp[i][j]<q[id].cost) continue;
                    if(st[i+1]&q[id].nx) continue;
                    if(dp[i+1][(q[id].nx)|st[i+1]]==-1) dp[i+1][(q[id].nx)|st[i+1]]=dp[i][j]+q[id].cost;
                    else dp[i+1][(q[id].nx)|st[i+1]]=min(dp[i+1][(q[id].nx)|st[i+1]],dp[i][j]+q[id].cost);
                }
            }
        }

        if(dp[n][0]!=-1&&dp[n][0]<=c) printf("YES\n");
        else printf("NO\n");
    }
    return 0;
}

 

posted @ 2017-01-17 17:48  Fighting_Heart  阅读(187)  评论(0编辑  收藏  举报