uvalive 6323 状态压缩DP

思路:dp[i][j][x]表示状态 i 以 j 为结束 得分为 x 的方案数。

#include<iostream>
#include<cstdio>
#include<algorithm>
#include<cmath>
#include<cstring>
using namespace std;
int dp[5000][13][40],g[5][5],d[13][13],n,l,ans;
bool vi[13],ntou[13];
struct Point{
    int x,y;
}p[13];
bool OK(int a,int b)
{
    int x1,y1,x2,y2,i;
    x1=p[a].x,y1=p[a].y;
    x2=p[b].x,y2=p[b].y;
    if(x1==x2){
        if(y1>y2)
            swap(y1,y2);
        for(i=y1+1;i<y2;i++) if(!vi[g[x1][i]]||ntou[g[x1][i]])
        return false;
    }
    if(y1==y2){
        if(x1>x2)
            swap(x1,x2);
        for(i=x1+1;i<x2;i++) if(!vi[g[i][y1]]||ntou[g[i][y1]])
            return false;
    }
    if(abs(x1-x2)==2&&abs(y1-y2)==2){
        int x=(x1+x2)/2;
        int y=(y1+y2)/2;
        if(!vi[g[x][y]]||ntou[g[x][y]])
            return false;
    }
    return true;
}
void init()
{
    int i,j,cnt=0;
    for(i=1;i<=3;i++){
        for(j=1;j<=4;j++){
            g[i][j]=++cnt;
            p[cnt].x=i,p[cnt].y=j;
        }
    }
    for(i=1;i<=12;i++){
        for(j=1;j<=12;j++){
            d[i][j]=abs(p[i].x-p[j].x)+abs(p[i].y-p[j].y);
        }
    }
}
void solve()
{
    int i,j,k,r;
    ans=0;
    int N=(1<<12)-1;
    for(i=0;i<12;i++)
        dp[1<<i][i+1][0]=1;
    for(i=1;i<=N;i++){
        memset(vi,0,sizeof(vi));
        for(k=0;k<12;k++) if(((1<<k)&i)) vi[k+1]=1;
        for(j=0;j<12;j++) if((((1<<j)&i))&&!ntou[j+1]){
            for(k=0;k<12;k++) if(((1<<k)&i)==0&&!ntou[k+1]&&OK(j+1,k+1)){
                //cout<<p[j+1].x<<" "<<p[j+1].y<<" "<<p[k+1].x<<" "<<p[k+1].y<<endl;
                for(r=0;r<=40;r++){
                    dp[i|(1<<k)][k+1][r+d[j+1][k+1]]+=dp[i][j+1][r];
                }
            }
        }
    }
    for(i=1;i<=N;i++){
        for(j=1;j<=12;j++){
            ans+=dp[i][j][l];
        }
    }
}
int main()
{
    int i,j,t,x,y;
    init();
    scanf("%d",&t);
    while(t--){
        memset(dp,0,sizeof(dp));
        memset(vi,0,sizeof(vi));
        memset(ntou,0,sizeof(ntou));
        scanf("%d%d",&l,&n);
        for(i=1;i<=n;i++){
            scanf("%d%d",&x,&y);
            ntou[g[x][y]]=1;
        }
        if(l>=40){
            printf("BAD MEMORY\n");
            continue;
        }
        solve();
        if(ans)
            printf("%d\n",ans);
        else
            printf("BAD MEMORY\n");
    }
    return 0;
}

 

posted @ 2013-10-11 08:41  fangguo  阅读(213)  评论(0编辑  收藏  举报