zoukankan      html  css  js  c++  java
  • SGU 222 Little Rooks

    SGU_222

    最近刚学了插头dp,所以就用插头dp那个模式写了这个题。

    可以用f[i][j][st]表示推到第i行第j列时,行和列上rook的状态为st时方案的种数。

    #include<stdio.h>
    #include<string.h>
    #define HASH 30007
    #define SIZE 1000010
    int N, K, rst, cst;
    struct Hashmap
    {
        int head[HASH], next[SIZE], state[SIZE], size;
        long long f[SIZE];
        void init()
        {
            memset(head, -1, sizeof(head));
            size = 0;
        }
        void push(int st, long long ans)
        {
            int i, h = st % HASH;
            for(i = head[h]; i != -1; i = next[i])
                if(st == state[i])
                {
                    f[i] += ans;
                    return ;
                }
            state[size] = st, f[size] = ans;
            next[size] = head[h];
            head[h] = size ++;
        }
    }hm[2];
    int encode(int rst, int cst)
    {
        return (rst << N) | cst;
    }
    void decode(int st)
    {
        cst = st & ((1 << N) - 1);
        rst = st >> N;
    }
    void dpblank(int i, int j, int cur)
    {
        int k;
        for(k = 0; k < hm[cur].size; k ++)
        {
            decode(hm[cur].state[k]);
            hm[cur ^ 1].push(hm[cur].state[k], hm[cur].f[k]);
            if(((1 << i) & rst) == 0 && ((1 << j) & cst) == 0)
                hm[cur ^ 1].push(encode(rst | (1 << i), cst | (1 << j)), hm[cur].f[k]);
        }
    }
    void solve()
    {
        int i, j, k, cur = 0;
        long long ans = 0;
        hm[cur].init();
        hm[cur].push(0, 1);
        for(i = 0; i < N; i ++)
            for(j = 0; j < N; j ++)
            {
                hm[cur ^ 1].init();
                dpblank(i, j, cur);
                cur ^= 1;
            }
        for(i = 0; i < hm[cur].size; i ++)
        {
            decode(hm[cur].state[i]);
            for(j = k = 0; j < N; j ++)
                if(rst & (1 << j))
                    ++ k;
            if(k == K)
                ans += hm[cur].f[i];
        }
        printf("%I64d\n", ans);
    }
    int main()
    {
        while(scanf("%d%d", &N, &K) == 2)
        {
            if(K > N)
                printf("0\n");
            else
                solve();
        }
        return 0;
    }
  • 相关阅读:
    4819: [Sdoi2017]新生舞会 分数规划
    [Sdoi2017]序列计数 矩阵优化dp
    SDOI2017相关分析 线段树
    loj SDOI2017数字表格
    bzoj 2527: [Poi2011]Meteors
    BZOJ2440: [中山市选2011]完全平方数
    GCD与莫比乌斯反演的勾当
    2870: 最长道路tree
    bzoj2152: 聪聪可可 点分治
    3545: [ONTAK2010]Peaks 平衡树,最小生成树
  • 原文地址:https://www.cnblogs.com/staginner/p/2461652.html
Copyright © 2011-2022 走看看