博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
互不侵犯king (状压dp)
阅读量:5172 次
发布时间:2019-06-13

本文共 1519 字,大约阅读时间需要 5 分钟。

互不侵犯king (状压dp)

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

  这道题如果普通dfs肯定会超时。为什么呢?我们发现一行中的状态是固定的,同时行与行之间的冲突情况也是固定的。而dfs重复枚举了每一行的状态,重复判断了这一行的状态是否与前一行相冲突。于是我们预处理出一行中的状态,同时预处理出两行状态的冲突情况,然后dp就行了。\(f[i][j][k]\)表示枚举到第i行,有j个国王,当前行状态的编号为k。它只能通过不与k冲突的上一行转移而来。于是就过了。

#include 
using namespace std;long long st[100];int cnt[100], now[10], map[100][100];int n, k, cntst;long long f[10][100][100];void dfs(int pos){ now[pos]=1; long long tmp=0; ++cntst; for (int i=1; i<=n; ++i){ tmp=(tmp<<1)+now[i]; cnt[cntst]+=now[i]; } st[cntst]=tmp; for (int i=pos+2; i<=n; ++i) dfs(i); now[pos]=0;}int main(){ scanf("%d%d", &n, &k); st[0]=0; cnt[0]=0; for (int i=1; i<=n; ++i) dfs(i); for (int i=0; i<=cntst; ++i) for (int j=0; j<=cntst; ++j) if ((st[i]&st[j])==0&& ((st[i]<<1)&st[j])==0&& ((st[i]>>1)&st[j])==0){ map[i][j]=1; map[j][i]=1; } f[0][0][0]=1; for (int i=1; i<=n; ++i) for (int j=0; j<=k; ++j) for (int st=0; st<=cntst; ++st){ if (cnt[st]>j) continue; for (int st2=0; st2<=cntst; ++st2){ if (!map[st][st2]) continue; f[i][j][st]+=f[i-1][j-cnt[st]][st2]; } } long long ans=0; for (int i=0; i<=cntst; ++i) ans+=f[n][k][i]; printf("%lld", ans); return 0;}

转载于:https://www.cnblogs.com/MyNameIsPc/p/7697661.html

你可能感兴趣的文章
Struts 2 常用技术
查看>>
树形DP
查看>>
python flask解决上传下载的问题
查看>>
语法测试
查看>>
CES1
查看>>
CES2
查看>>
文件方式实现完整的英文词频统计实例
查看>>
单个SWF文件loading加载详解(转)
查看>>
SQLServer中的CTE通用表表达式
查看>>
C# 3.0 LINQ的准备工作
查看>>
静态代码审查工具FxCop插件开发(c#)
查看>>
创建代码仓库
查看>>
理解裸机部署过程ironic
查看>>
Django 组件-ModelForm
查看>>
zabbix 二 zabbix agent 客户端
查看>>
大数据分析中,有哪些常见的大数据分析模型?
查看>>
如何防止Arp攻击
查看>>
ClassList 标签的用法
查看>>
小细节:Java中split()中的特殊分隔符 小数点
查看>>
【编程思想】【设计模式】【行为模式Behavioral】中介者模式Mediator
查看>>