LOJ 10170 -「一本通 5.4 例 1」骑士

题面

题目传送门

在 $N*N$ 的棋盘上放 $K$ 个国王,国王可攻击相邻的 $8$ 个格子,求使它们无法互相攻击的方案总数。

思路

状压 DP 的模板,以前 DP 技能一直没怎么点,现在数据结构什么的都差不多了,开始补 DP。

预处理

对于每一行来说,我们可以用二进制来表示当前这一行的放置状态。然后再压成十进制。

然后预处理出对于一行来说的所有状态(dfs)。

用 $s[i]$ 表示对于一行的第 i 种状态, $t[i]$ 表示这种状态用掉多少个棋子。

用 $f[i][j][k]$ 表示第 i 行,状态为 j,总共(包括之前)用了 k 个棋子的方法数。

然后用位运算来判断前后两行是否合法,转移就好了。

代码

#include<bits/stdc++.h>
using namespace std;
long long n,K,cnt=0,s[100000],t[100000],f[20][200][200],ans=0;
void dfs(int now,int sum,int pos){
	if (pos>=n){
		s[++cnt]=now;
		t[cnt]=sum;
		return;
	}
	dfs(now,sum,pos+1);
	dfs(now+(1<<pos),sum+1,pos+2);
}
int main(){
	cin>>n>>K;
	dfs(0,0,0);
	for (int i=1;i<=cnt;i++){
		f[1][i][t[i]]=1;
	}
	for (int i=2;i<=n;i++){
		for (int j=1;j<=cnt;j++){
			for (int k=1;k<=cnt;k++){
				if ((s[j]&s[k])||((s[j]<<1)&s[k])||((s[j]>>1)&s[k])){
					continue;
				}
				for (int x=K;x>=t[j];x--){
					f[i][j][x]+=f[i-1][k][x-t[j]];
				}
			}
		}
	}
	for (int i=1;i<=cnt;i++){
		ans+=f[n][i][K];
	}
	cout<<ans;
}
作者: solstice23
本文采用 CC BY-NC-SA 4.0 协议
暂无评论

发送评论 编辑评论


				
|´・ω・)ノ
ヾ(≧∇≦*)ゝ
(☆ω☆)
(╯‵□′)╯︵┴─┴
 ̄﹃ ̄
(/ω\)
∠( ᐛ 」∠)_
(๑•̀ㅁ•́ฅ)
→_→
୧(๑•̀⌄•́๑)૭
٩(ˊᗜˋ*)و
(ノ°ο°)ノ
(´இ皿இ`)
⌇●﹏●⌇
(ฅ´ω`ฅ)
(╯°A°)╯︵○○○
φ( ̄∇ ̄o)
ヾ(´・ ・`。)ノ"
( ง ᵒ̌皿ᵒ̌)ง⁼³₌₃
(ó﹏ò。)
Σ(っ °Д °;)っ
( ,,´・ω・)ノ"(´っω・`。)
╮(╯▽╰)╭
o(*////▽////*)q
>﹏<
( ๑´•ω•) "(ㆆᴗㆆ)
😂
😀
😅
😊
🙂
🙃
😌
😍
😘
😜
😝
😏
😒
🙄
😳
😡
😔
😫
😱
😭
💩
👻
🙌
🖕
👍
👫
👬
👭
🌚
🌝
🙈
💊
😶
🙏
🍦
🍉
😣
Source: Telegram @AmashiroNatsukiEars_NoWord Sticker
Source: Telegram Animated Emojis
Source: github.com/k4yt3x/flowerhd
颜文字
Emoji
AmashiroNatsukiEars
Telegram Emojis
小恐龙
花!
上一篇
下一篇