acwing 1064 小国王 线性状态压缩DP

本文是一篇C++编程题目解答,使用动态规划方法解决在一个给定大小的棋盘上放置国王的问题,确保每行和每列最多只有一个国王且没有相邻的国王。
摘要由CSDN通过智能技术生成

在这里插入图片描述
输入

3 2

输出

16

🍺 AC code

#include<iostream>
#include<cstring>
#include<cstdio>
#include<algorithm>
#include<vector>

using namespace std;

typedef long long ll;
const int N = 12;
const int M = 1 << 10, K = 110;//k表示国王数
int n,m;
vector<int> state;//存储所有单行合法状态
int id[M];//存的是每一个状态和这个它的下标之间的对应关系
vector<int> head[M];//记录每个状态可以转到哪些其他的状态
int cnt[M];//记录状态 i 里边 1 的个数

ll f[N][K][M];

bool check(int state)
{
	for(int i = 0; i < n; i++)
		if((state >> i & 1) && (state >> (i + 1) & 1))
			return false;
	return true;
}
// 计算 state 二进制 里边有多少个 1
int count(int state )
{
	int res = 0;
	for(int i = 0; i < n; i++)
		res += state >> i & 1;
	return res;
}

int main(){
	cin >> n >> m;// n是 棋盘边长,m是 国王个数
	
//	预处理单行合法状态
	for(int i = 0; i < 1 << n; i++)
		if(check(i))
		{
			state.push_back(i);
			id[i] = state.size()-1;//id存的是 状态 i 所对应的state下标
			cnt[i] = count(i); 		
		}
	
//	预处理状态之间是否可以转移(即上一行状态和下一行状态是否冲突)
	for(int i = 0; i < state.size(); i++)// i是当前状态的下标
		for(int j = 0; j < state.size(); j++)// j 是下一个状态的下标
		{
			int a = state[i];
			int b = state[j];
//			没有冲突的1			没有连续的两个 1
			if((a & b) == 0 && check(a | b))//合法
				head[i].push_back(j);//表示 i 下边可以接 j
		}
	
//	开始DP
	f[0][0][0] = 1;
	for(int i = 1; i <= n+1; i++)// i 表示行数
		for(int j = 0; j <= m; j++)// j 表示国王数
			for(int a = 0; a < state.size(); a++)// a 表示第 i 行状态的下标
				for(int b = 0; b < head[a].size(); b++)// b 表示第 i+1 可能转移到的状态
				{
					int c = cnt[state[a]];//c 记录 第i行状态 state[a]中 1 的个数
//			第 i 行采取k状态表示 会 放置 c 个国王,当前状态 f[i][j][k] 表示前i层放置了 j 个国王
//			所以 c 的上限是 j
					if(j >= c)
						f[i][j][a] += f[i-1][j-c][head[a][b]];
				}
					
	cout << f[n+1][m][0] << endl;
	
	return 0;
}




👨‍🏫 参考题解

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值