zoukankan      html  css  js  c++  java
  • dp--状压dp

    Problem Description

    互不侵犯
    在N×N的棋盘里面放K个国王,使他们互不攻击,共有多少种摆放方案。国王能攻击到它上下左右,以及左上左下右上右下八个方向上附近的各一个格子,共8个格子。

    Analysis of ideas

    把每一行的每一个状态用一个二进制数表示
    定义dp[i][j][k]为第i行,状态为j,已经放了k个棋子的方案数

    Accepted code

    #pragma GCC optimize(2)
    #include <bits/stdc++.h>
    using namespace std;
    #define int long long
    int n,k;
    
    int dp[10][1024][100];        //第i行状态为j,放了k个国王
    
    vector<int> v;            //枚举可用的状态
    
    
    int count(int x)        //计算x1的个数
    {
        int res = 0;
        while(x)
        {
            res += x%2;
            x /= 2;
        }
        return res;
    }
    
    signed main()
    {
        cin>>n>>k;
        int mx = 1<<n;                //状态最多有1<<n个
        for(int i = 0; i < mx; i++) 
        {
            if((i&(i<<1)) == 0 && (i&(i>>1)) == 0) v.push_back(i);            //左边和右边没有1就是可用的状态
        }
        dp[0][0][0] = 1;                //初始化
        for(int i = 1; i <= n; i++) 
        {
            for(int j : v)      //枚举第i行状态j
            {
                for(int l : v)      //枚举第i-1行l
                {   
                    if((j&l) || (j&(l<<1)) || (j&(l>>1))) continue;        //不能互相攻击到
                    for(int h = 0; h <= k; h++)            //枚举已经放置的国王个数
                    {
                        dp[i][j][h+count(j)] += dp[i-1][l][h];
                    }
                }
            }
        }
        int ans = 0;
        for(int i : v) 
        {
            ans += dp[n][i][k];
        }
        cout<<ans<<endl;
        return 0;
    }
    
  • 相关阅读:
    数组,一维,二维,多维
    类函数:string、math
    while和for的内嵌
    循环语言(for)
    选择语言之switch case
    程序语言
    语言、数据和运算符
    原理之一,进制转换
    HTML第一部分
    结构体共用变量 递归
  • 原文地址:https://www.cnblogs.com/hezongdnf/p/12276068.html
Copyright © 2011-2022 走看看