zoukankan      html  css  js  c++  java
  • 洛谷 P1896 [SCOI2005]互不侵犯 (状态压缩DP)

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

    注:数据有加强(2018/4/25)

    输入输出格式
    输入格式:
    只有一行,包含两个数N,K ( 1 <=N <=9, 0 <= K <= N * N)

    输出格式:
    所得的方案数

    输入输出样例
    输入样例#1:
    3 2
    输出样例#1:
    16

    题意:

    思路:

    动态规划,
    定义状态dp[i][j][k] 代表到第i行,第j个状态(j所代表的二进制信息状态),放了k个国王的方案数。
    代码中有详细注释

    细节见代码:

    #include <iostream>
    #include <cstdio>
    #include <cstring>
    #include <algorithm>
    #include <cmath>
    #include <queue>
    #include <stack>
    #include <map>
    #include <set>
    #include <vector>
    #include <iomanip>
    #define ALL(x) (x).begin(), (x).end()
    #define rt return
    #define dll(x) scanf("%I64d",&x)
    #define xll(x) printf("%I64d
    ",x)
    #define sz(a) int(a.size())
    #define all(a) a.begin(), a.end()
    #define rep(i,x,n) for(int i=x;i<n;i++)
    #define repd(i,x,n) for(int i=x;i<=n;i++)
    #define pii pair<int,int>
    #define pll pair<long long ,long long>
    #define gbtb ios::sync_with_stdio(false),cin.tie(0),cout.tie(0)
    #define MS0(X) memset((X), 0, sizeof((X)))
    #define MSC0(X) memset((X), '', sizeof((X)))
    #define pb push_back
    #define mp make_pair
    #define fi first
    #define se second
    #define eps 1e-6
    #define gg(x) getInt(&x)
    #define chu(x) cout<<"["<<#x<<" "<<(x)<<"]"<<endl
    using namespace std;
    typedef long long ll;
    ll gcd(ll a,ll b){return b?gcd(b,a%b):a;}
    ll lcm(ll a,ll b){return a/gcd(a,b)*b;}
    ll powmod(ll a,ll b,ll MOD){ll ans=1;while(b){if(b%2)ans=ans*a%MOD;a=a*a%MOD;b/=2;}return ans;}
    inline void getInt(int* p);
    const int maxn=1000010;
    const int inf=0x3f3f3f3f;
    /*** TEMPLATE CODE * * STARTS HERE ***/
    
    int n,k;
    ll dp[15][(1<<10)][11*11];
    int need[(1<<11)];
    int getnum(int x)
    {
        int res=0;
        int num=x;
        if(need[num]!=-1)
        {
            return need[x];
        }
        while(x)
        {
            if(x&1)
            {
                res++;
            }
            x>>=1;
        }
        need[num]=res;
        return res;
    }
    bool can[maxn];
    int main()
    {
        //freopen("D:\common_text\code_stream\in.txt","r",stdin);
        //freopen("D:\common_textcode_stream\out.txt","w",stdout);
        
        gbtb;
        memset(need,-1,sizeof(need));
        cin>>n>>k;
        int maxstate=(1<<n)-1;
        for(int i=0;i<=maxstate;i++)
        {
            if((i&(i<<1))==0&&(i&(i>>1))==0)// 本行里没有相邻的1
            {
                can[i]=1;
                dp[1][i][getnum(i)]=1ll;// 初始化第一行的dp值
            }
        }
        for(int i=2;i<=n;i++)
        {
            for(int j=0;j<=maxstate;j++)// 枚举当前行的所有状态j
            {
                if(can[j])
                for(int w=0;w<=maxstate;w++)// 枚举上一行的所有状态w
                {
                    if(can[w]==1&&((j&w)==0)&&((j<<1)&w)==0&&((j>>1)&w)==0)// 确保当前的w是合法状态,并且与上一行没有重叠的1,并且当前j的向左移动一次一位,向右移动一次,均和w没有重叠的1 ,这样就确保了国王互不侵犯。
                    {
                        int num=getnum(j);
                        for(int l=k;l>=num;l--)
                            dp[i][j][l]+=dp[i-1][w][l-num];
                    }
                }
            }
        }
        ll ans=0ll;
        for(int i=0;i<=maxstate;i++)
        {
            ans+=dp[n][i][k];// 累加答案。
        }
        cout<<ans<<endl;
        
        
        return 0;
    }
    
    inline void getInt(int* p) {
        char ch;
        do {
            ch = getchar();
        } while (ch == ' ' || ch == '
    ');
        if (ch == '-') {
            *p = -(getchar() - '0');
            while ((ch = getchar()) >= '0' && ch <= '9') {
                *p = *p * 10 - ch + '0';
            }
        }
        else {
            *p = ch - '0';
            while ((ch = getchar()) >= '0' && ch <= '9') {
                *p = *p * 10 + ch - '0';
            }
        }
    }
    
    
    
    
    
    本博客为本人原创,如需转载,请必须声明博客的源地址。 本人博客地址为:www.cnblogs.com/qieqiemin/ 希望所写的文章对您有帮助。
  • 相关阅读:
    自动化运维
    rabbitmq常见问题
    常见的排序算法
    rabbitmq
    redis-其他应用
    redis之缓存穿透、雪崩、击穿
    redis-cluster(集群)
    redis -sentinel(哨兵)
    redis持久化
    redis简介
  • 原文地址:https://www.cnblogs.com/qieqiemin/p/11148131.html
Copyright © 2011-2022 走看看