码迷,mamicode.com
首页 > 其他好文 > 详细

[SCOI2005]互不侵犯

时间:2020-07-05 00:38:17      阅读:58      评论:0      收藏:0      [点我收藏+]

标签:lag   棋盘   cin   include   name   else   ||   turn   背包   

题目描述

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


由于每摆上一个棋子,需要查看周围9个位置,导致搜索的复杂度直接爆炸(n*n个格子里选k个格子,并且还得满足条件)

因此需要预处理每一行的合法状态,然后进行递推(状压dp),每一位所记录的状态都是合法的

对于每一行,先枚举这一行的预备状态,然后枚举这一行的预备容量(类似背包枚举容量),再枚举上一行的状态(这个状态满足递推关系所以满足题目条件),如果两行judge合法则从上一行的状态转移到这一行

设上一行的状态下标为k,这一行的状态下标为j(其所包含1的数量为num[j])

即写出状态转移方程:\(dp[i][l][j] += dp[i - 1][l - num[j]][k]\)(类似背包,如果l-num[j]有状态会被加上来,没有就当无事发生);

别忘了初始状态为dp[0][0][0]=1,即第0行没有摆棋子的0号状态为合法状态

最后统计第n行有k个棋子的每个状态所满足条件的合法状态数即可

记得开long long


#pragma GCC optimize(2)
#include<bits/stdc++.h>
#define ll long long
#define fastio {ios::sync_with_stdio(false);cin.tie(NULL);cout.tie(NULL);};
using namespace std;
const int inf = 1e9 + 7;
const int maxn = 1e4 + 10;

vector<pair<ll,ll> >zt;

ll dp[11][200][200];

ll judge(ll x)
{
    ll cnt = 0;
    int flag = 0;
    while (x)
    {
        if (x & 1)
        {
            if (!flag)
                flag = 1;
            else
                return 0;
            cnt++;
        }
        else
            flag = 0;
        x >>= 1;
    }
    return cnt;
}

int main()
{
    fastio;
    ll n, K;
    cin >> n >> K;
    zt.push_back({0,0});
    for (int i = 1; i < 1 << n; i++)
    {
        ll tot;
        if (tot = judge(i))
        {
            //cout << i << " " << tot << endl;
            zt.push_back({ i,tot });
        }
    }
    dp[0][0][0] = 1;
    for (int i = 1; i <= n; i++)
        for (int j = 0; j < zt.size(); j++)
            for (int l = zt[j].second; l <= K; l++)
                for (int k = 0; k < zt.size(); k++)
                {
                    int tmp = zt[j].first, ttmp = zt[k].first;
                    if (tmp & ttmp || (tmp << 1) & ttmp || (tmp >> 1)& ttmp)continue;
                    dp[i][l][j] += dp[i - 1][l - zt[j].second][k];
                }
    ll ans = 0;
    for (int i = 0; i < zt.size(); i++)
        ans += dp[n][K][i];
    cout << ans;
    return 0;
}

[SCOI2005]互不侵犯

标签:lag   棋盘   cin   include   name   else   ||   turn   背包   

原文地址:https://www.cnblogs.com/ruanbaiQAQ/p/13237175.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!