• 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;
    }
  • 相关阅读:
    leetcode_697. 数组的度
    645. 错误的集合
    leetcode_448. 找到所有数组中消失的数字
    leetcode_628. 三个数的最大乘积
    leetcode_414. 第三大的数
    leetcode_495. 提莫攻击
    leetcode_485. 最大连续1的个数
    在 Mac、Linux、Windows 下Go交叉编译
    Goland基本操作
    etcd搭建及基本使用
  • 原文地址:https://www.cnblogs.com/staginner/p/2461652.html
Copyright © 2020-2023  润新知