【xdoj难题集】 1117 Insert Orz Pandas

很快地想出了一个不是很快的方法,反正很想知道那些3ms的是怎么做出来的。。。只能膜拜了orz

看来一眼觉得是状压dp然后就算了一下复杂度,首先因为n最大是10所以没层需要有2的10次方种情况,然后100层,每层最多的情况应该是C10 5也就是250种左右,勉强可以。
然后详细说一下过程,因为n最大是10,而且每个格子最多只能放一只panda,所以每层的熊猫数量为a[i]的情况肯定是CNa[i]种,然后把每种和之前的一种情况亦或一下就是新情况了。所以存储每一层可能出现的01情况的数量即可。

顺便说一下那个带comb的复杂的位运算式子是求所有字典序k的排列的。

贴代码

# include <stdio.h>
# include <string.h>

const int Mod = 1e9 + 7;
const int MAX_N = 10;
const int MAX_M = 100;

int A[MAX_M], B[MAX_N];
int N, M;

int dp[MAX_M + 1][1 << MAX_N]; 

void solve()
{
    memset(dp , 0 , sizeof(dp));
    dp[0][0] = 1;

    int i, j;
    for(i = 1 ; i <= M ; i++)
    {
        for(j = 0 ; j < (1 << N) ; j++)
        {
            if(!dp[i - 1][j])
                continue;

            int comb = (1 << A[i - 1]) - 1;
            while(comb < 1 << N)
            {
                dp[i][comb ^ j] += dp[i - 1][j];
                if(dp[i][comb ^ j] >= Mod)
                    dp[i][comb ^ j] -= Mod;

                int x = comb & -comb, y = comb + x;
                comb = ((comb & ~y) / x >> 1) | y;
            }
        }
    }
    int s = 0;
    for(i = 0 ; i < N ; i++)
    {
        s <<= 1;
        s |= B[i];
    }

    printf("%d\n", dp[M][s]);
}

int main()
{


    while(~scanf("%d %d", &N, &M))
    {
        int i;
        for(i = 0 ; i < M ; i++)
            scanf("%d", &A[i]);

        for(i = 0 ; i < N ; i++)
            scanf("%d", &B[i]);

        solve();
    }

    return 0;
} 

猜你喜欢

转载自blog.csdn.net/qq_40772738/article/details/80015778