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;
    }
    
  • 相关阅读:
    September 17th 2016 Week 38th Saturday
    【2016-09-16】UbuntuServer14.04或更高版本安装问题记录
    September 16th 2016 Week 38th Friday
    September 11th 2016 Week 38th Sunday
    September 12th 2016 Week 38th Monday
    September 10th 2016 Week 37th Saturday
    September 9th 2016 Week 37th Friday
    c++暂停
    八皇后问题
    ( 转转)Android初级开发第九讲--Intent最全用法(打开文件跳转页面等)
  • 原文地址:https://www.cnblogs.com/tpgzy/p/9743483.html
Copyright © 2011-2022 走看看