HDU 6407 Pop the Balloons

版权声明:本文为博主原创文章,未经博主允许必须转载。 https://blog.csdn.net/qq_35950004/article/details/81709049

题意:Ex打气球,气球爆了会吹飞同行同列的气球,求引爆K次气球使所有气球消失的方案数。
行列:N<=12 , M<=20 。K <=20

各种分析,然后发现你只能打K行,每行每列只能打一个,那么就二进制枚举呗(N<=12)
然后一个状压DP就行了,
从左到右枚举列 , 如果这列除了这K行外还有气球存在,那么这列一定要引爆一个,否则可以不引爆,但是最多只能引爆一个。
答案居然炸Long long 。。。。。。

有点卡常
AC Code:

#include<bits/stdc++.h>
#define maxn 21
#define mod 1000000000ll
#define LL long long
using namespace std;

int n,m,k;
int c[maxn],lg[1<<14];
bool M[maxn][maxn];
int had[maxn];
LL ans[maxn] , dp[2][1<<13] ,fac[maxn];
char s[maxn];

void clear(LL dp[],int siz)
{
    siz=(1<<siz);
    for(int i=0;i<siz;i++)
        dp[i] = 0;
}

void dfs(int now,int k)
{
    if(now == n)
    {

        int now=1 , pre=0;
        clear(dp[pre],k) , dp[pre][(1<<k)-1]=1;
        for(int i=0;i<m;i++,swap(now,pre))
        {
            clear(dp[now],k);
            for(int j=0;j<1<<k;j++)
                if(dp[pre][j])
                    for(int tmp=j;tmp;tmp-=tmp&-tmp)
                        if(M[c[lg[tmp & -tmp]]][i])
                            dp[now][j - (tmp & -tmp)] += dp[pre][j];

            if(!had[i])
                for(int j=0;j<1<<k;j++)
                    dp[now][j] += dp[pre][j];
        }

        ans[k] = ans[k] + dp[pre][0];
        return;
    }

    c[k] = now;
    dfs(now+1,k+1);
    for(int j=0;j<m;j++)
        if(M[now][j])
            had[j]++;
    dfs(now+1,k);
    for(int j=0;j<m;j++)
        if(M[now][j])
            had[j]--;
}

int main()
{
    int T;
    for(int i=0;i<13;i++) lg[1<<i] = i;
    fac[0] = 1;
    for(int i=1;i<13;i++) fac[i] = fac[i-1] * i;
    for(scanf("%d",&T);T--;)
    {
        scanf("%d%d%d",&n,&m,&k);
        memset(ans,0,sizeof ans);
        for(int i=0;i<n;i++)
        {
            scanf("%s",s);
            for(int j=0;j<m;j++)
                M[i][j] = (s[j] == 'Q');
        }

        memset(had,0,sizeof had);
        dfs(0,0);
        for(int i=1;i<=k;i++)
        {
            LL a1=0,a2=0,a3=0, c , d;
            a3 += (ans[i] % mod) * (fac[i] % mod);
            a2 += (ans[i] % mod) * (fac[i] / mod) + (ans[i] / mod) * (fac[i] % mod);
            a1 += (ans[i] / mod) * (fac[i] / mod);
            if(a3 >= mod) a2 += a3 / mod , a3 %= mod;
            if(a2 >= mod) a1 += a2 / mod , a2 %= mod;
            if(a1)
                printf("%lld%09lld%09lld\n",a1,a2,a3);
            else if(a2)
                printf("%lld%09lld\n",a2,a3);
            else
                printf("%lld\n",a3);
        }
    }
}

猜你喜欢

转载自blog.csdn.net/qq_35950004/article/details/81709049
pop