• [SCOI2005]互不侵犯


    嘟嘟嘟

     

    做完[NOI2001]炮兵阵地这道题,顿时觉得此题好水~~15分钟AC

    令dp[i][j][k]表示到第 i 行放了 j 个国王,该行状态为 k 时的方案数。然后dp的时候第一层循环枚举 i,第二层 j,如果j 合法的话,再枚举第三层 i - 1行的状态 k,然后如果k合法且 j 和k不冲突的话,再枚举国王数量h,于是就有:

        dp[i][h][j] += dp[i - 1][h - sum[j]][k]

    至于如何判断j和k不冲突,那自然是 j & k == 0 且 j | k状态是合法的。

    优化就是先预处理所有合法的 j 和k。

    然后别忘了dp[1]单独处理。

     1 #include<cstdio>
     2 #include<iostream>
     3 #include<cmath>
     4 #include<algorithm>
     5 #include<cstring>
     6 #include<cstdlib>
     7 #include<cctype>
     8 #include<vector>
     9 #include<stack>
    10 #include<queue>
    11 using namespace std;
    12 #define enter puts("") 
    13 #define space putchar(' ')
    14 #define Mem(a) memset(a, 0, sizeof(a))
    15 typedef long long ll;
    16 typedef double db;
    17 const int INF = 0x3f3f3f3f;
    18 const db eps = 1e-8;
    19 const int max_sta = 100;        //经测试。合法的状态最多只有89种 
    20 inline ll read()
    21 {
    22     ll ans = 0;
    23     char ch = getchar(), last = ' ';
    24     while(!isdigit(ch)) {last = ch; ch = getchar();}
    25     while(isdigit(ch)) {ans = ans * 10 + ch - '0'; ch = getchar();}
    26     if(last == '-') ans = -ans;
    27     return ans;
    28 }
    29 inline void write(ll x)
    30 {
    31     if(x < 0) x = -x, putchar('-');
    32     if(x >= 10) write(x / 10);
    33     putchar(x % 10 + '0');
    34 }
    35 
    36 int n, m;
    37 int sum[max_sta], s[max_sta], cnt = 0;
    38 bool ok[1000];
    39 ll dp[10][100][max_sta];
    40 
    41 int getsum(int x)
    42 {
    43     int ret = 0;
    44     for(; x; x >>= 1) ret += x & 1;
    45     return ret;
    46 }
    47 void init()
    48 {
    49     for(int i = 0; i < (1 << n); ++i)
    50         if(!(i & (i << 1)) && !(i & (i >> 1)))
    51         {
    52             s[++cnt] = i;
    53             ok[i] = 1;
    54             sum[cnt] = getsum(i);    
    55             dp[1][sum[cnt]][cnt]++;
    56         }
    57 }
    58 
    59 int main()
    60 {
    61     n = read(); m = read();
    62     init();
    63     for(int i = 2; i <= n; ++i)
    64         for(int j = 1; j <= cnt; ++j) 
    65             for(int k = 1; k <= cnt; ++k) 
    66                 if(!(s[j] & s[k]) && ok[s[j] | s[k]])
    67                     for(int h = sum[j]; h <= m; ++h)
    68                         dp[i][h][j] += dp[i - 1][h - sum[j]][k];
    69     ll ans = 0;
    70     for(int i = 1; i <= cnt; ++i) ans += dp[n][m][i];
    71     write(ans); enter;
    72     return 0;
    73 }
    View Code
  • 相关阅读:
    安装好k8s后,使用kubectl get cs 查看状态,发现 controller-manager scheduler Unhealthy
    k8s 去掉node标签 难去的
    项目中常用到的布局 flex
    scanf输入空格
    sed和awk学习第一天
    线程池
    线程间通信 | 等待唤醒机制
    创建线程的三种方法详细对比
    EXCEL中VLOOKUP函数的使用
    Vulnhub实战靶场:GAARA: 1
  • 原文地址:https://www.cnblogs.com/mrclr/p/9622197.html
Copyright © 2020-2023  润新知