zoukankan      html  css  js  c++  java
  • Bzoj 1087: [SCOI2005]互不侵犯King

    Bzoj 1087: [SCOI2005]互不侵犯King

    题链
    今天下午没有事情,学习了一下(状压DP).感觉非常nice.
    (f[i][j][k])表示到达第(i)(j)个状态使用了(k)的国王的方案数.
    首先筛出行合法的状态.然后二进制操作.
    我这里设(a)为合法状态.
    转移的时候.
    (a[i] & a[j])((a[i] << 1) & a[j])(( (a[j] << 1) & a[i] ))
    如果这三者等于(0)的话,状态可以转移.

    // luogu-judger-enable-o2
    #include <iostream>
    #include <cstdio>
    #include <cstring>
    using namespace std;
    const int maxN = 16 + 7;
    const int max_num = 1030;
    
    int n,k;
    long long f[18][2000][100];
    
    int cnt ;
    int Q[40];
    int a[2000];
    int tal[2000];
    
    void work() {
        int num = 0,tmp = 0;
        for(int i = 0;i < n;++ i) {
            if(Q[i]) num += (1 << i),tmp ++ ;
        }
        cnt ++;	
        a[cnt] = num;
        tal[cnt] = tmp;
        return ;
    }
    
    void dfs(int tot) {
        if(tot == n) {work();return ;}
        dfs(tot + 1);
        if(!Q[tot - 1]) {
            Q[tot] = 1;
            dfs(tot + 1);
        }
        Q[tot] = 0;
        return ;
    }
    
    int main()
    {
        scanf("%d%d",&n,&k);
        	Q[0] = 1;
            dfs(1);
            Q[0] = 0;
            dfs(1);
            for(int i = 1;i <= cnt;++ i) f[1][i][tal[i]] = 1;
            for(int i = 2;i <= n;++ i) {
                for(int j = 1;j <= cnt;++ j) {
                    for(int l = 1;l <= cnt;++ l) {
                        if(a[j] & a[l]) continue;
                        if((a[j] << 1) & a[l]) continue;
                        if((a[j] >> 1) & a[l]) continue;
                        for(int gs = tal[j];gs <= k;++ gs) {
                            f[i][j][gs] += f[i - 1][l][gs - tal[j]];
                        }
                    }
                }
            }
            long long ans = 0;
            for(int i = 1;i <= cnt;++ i) {
                ans += (long long)f[n][i][k];
            }
        printf("%lld",ans);	
        return 0;
    } 
    

    我们发现(n,m)特别小.显然是可以搜索暴力枚举出来的.

    #include <iostream>
    #include <cstdio>
    const int maxN = 100;
    
    long long ans[maxN][maxN] = {
    {0},
    {1,1},
    {1,4,0,0,0},
    {1,9,16,8,1,0,0,0,0,0},
    {1,16,78,140,79,0,0,0,0,0,0,0,0,0,0,0,0},
    {1,25,228,964,1987,1974,978,242,27,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0},
    {1,36,520,3920,16834,42368,62266,51504,21792,3600,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0},
    {1,49,1020,11860,85275,397014,1220298,2484382,3324193,2882737,1601292,569818,129657,18389,1520,64,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0},
    {1,64,1806,29708,317471,2326320,12033330,44601420,119138166,229095676,314949564,305560392,204883338,91802548,25952226,4142000,281571,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0},
    {1,81,2968,65240,962089,10087628,77784658,450193818,1979541332,6655170642,17143061738,33787564116,50734210126,57647295377,49138545860,31122500764,14518795348,4959383037,1237072414,224463798,29275410,2673322,163088,6150,125,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0},
    };
    
    int main() {
        int n,m;
        scanf("%d%d",&n,&m);
        printf("%lld",ans[n][m]);
        return 0;
    }
    
  • 相关阅读:
    怎样设定目标(六)如何时刻保持在目标的正确轨道上
    怎样设定目标(五)——设定目标失败的七大原因
    怎样设定目标(四)如何规划成功的新年目标
    怎样设定目标(三)——目标设定前的准备
    CMake笔记(一)
    开源IDE code blocks黑色主题
    函数指针
    getRealPath函数编译报错问题
    Intellij IDEA添加项目依赖
    structs2.8创建拦截器
  • 原文地址:https://www.cnblogs.com/tpgzy/p/9743483.html
Copyright © 2011-2022 走看看