Description

用字符矩阵来表示一个8x8的棋盘,'.'表示是空格,'P'表示人质,'K'表示骑士。每一步,骑士可以移动到他周围的8个方格中的任意一格。如果你移动到的格子中有人质(即'P'),你将俘获他。但不能移到出棋盘或当前是'K'的格子中。请问最少要移动多少步骑士才能俘获所有的人质。

Input Format

第一行一个整数N(<=5),表示有多少个棋盘。即多组测试数据。每一组有8行,每行8个字符。字符只有'.',大写'P',大写'K'三种字符。'P'和'K'的个数范围都在[1,10]。

Output Format

有N行,每行只一个整数,相应棋盘俘获全部人质所需要的最少步数。

Sample Input

2

P......P

........

........

........

...KK...

........

........

P......P

.....P.P

..K....P

....K...

..PP...P

...K..KK

........

K.......

KP.K....

Sample Output

20

9

Solution

多亏参考了省队队长的代码,%yh,

可以发现骑士和人质数量极小,考虑状压DP。

虽然骑士有好多个,实际上他们不影响,可以先分别做DP,不妨让F[k][i][S]表示第k个骑士在第i个点且俘获状态为S的最少步数,易得F[k][j][S|1<<(j-1)]=min{f[k][i][S]+ptp[i][j]},其中ptp[i][j]表示人质i到人质j的最少步数

这里有个关键的地方就是骑士可以向8个方向移动,所以2点之间最少步数应为max(|x1-x2|,|y1-y2|)

然后记录每个骑士i对于状态S的最少步数,我的代码是用F[k][0][S]表示

接下来在做一次DP,用G[i][S]表示前i个骑士对于状态S的最少步数,

则G[i][S]=min{G[i-1][S^S2]+F[i][S2]},1<=S2<=最终状态,且(S | S2) == S,答案就很明显了

Code

#include <cstdio>
#include <cmath>
#include <cstring>
#include <algorithm>
#define N 12
using namespace std; struct info {
int x, y;
} k[N], p[N];
int T, knum, pnum, dis[N][N], f[N][N][1 << N], ptp[N][N], ans[N][1 << N]; inline void Init() {
memset(dis, 0, sizeof(dis));
knum = pnum = 0;
for (int i = 1; i <= 8; ++i)
for (int j = 1; j <= 8; ++j) {
char ch = getchar();
while (ch != '.' && ch != 'K' && ch != 'P') ch = getchar();
if (ch == 'K') k[++knum] = (info) {i, j};
if (ch == 'P') p[++pnum] = (info) {i, j};
} for (int i = 1; i <= knum; ++i)
for (int j = 1; j <= pnum; ++j) {
int x1 = k[i].x, y1 = k[i].y, x2 = p[j].x, y2 = p[j].y;
dis[i][j] = max(fabs(x1 - x2), fabs(y1 - y2));
}
for (int i = 1; i <= pnum; ++i)
for (int j = i + 1; j <= pnum; ++j) {
int x1 = p[i].x, y1 = p[i].y, x2 = p[j].x, y2 = p[j].y;
ptp[i][j] = ptp[j][i] = max(fabs(x1 - x2), fabs(y1 - y2));
}
} inline void DP(int k) {
for (int i = 1; i <= pnum; ++i)
f[k][i][1 << (i - 1)] = dis[k][i];
for (int S = 1; S < (1 << pnum); ++S)
for (int i = 1; i <= pnum; ++i)
if (S & (1 << (i - 1)))
for (int j = 1; j <= pnum; ++j)
if (!(S & (1 << (j - 1))))
f[k][j][S | (1 << (j - 1))] = min(f[k][j][S | (1 << (j - 1))], f[k][i][S] + ptp[i][j]);
} int main() {
scanf("%d", &T);
while (T--) {
Init(); memset(f, 0x3f, sizeof(f));
for (int k = 1; k <= knum; ++k) {
DP(k);
for (int S = 1; S < (1 << pnum); ++S)
for (int i = 1; i <= pnum; ++i)
f[k][0][S] = min(f[k][0][S], f[k][i][S]);
} memset(ans, 0x3f, sizeof(ans));
ans[0][0] = 0;
for (int i = 1; i <= knum; ++i) {
ans[i][0] = 0;
for (int S = 1; S < (1 << pnum); ++S) {
ans[i][S] = ans[i - 1][S];
for (int g = 1; g < (1 << pnum); ++g) {
if ((S | g) != S) continue;
ans[i][S] = min(ans[i][S], ans[i - 1][S ^ g] + f[i][0][g]);
}
}
}
printf("%d\n", ans[knum][(1 << pnum) - 1]);
}
return 0;
}

Kings(状压DP)的更多相关文章

  1. SGU 223 Little Kings(状压DP)

    Description 用字符矩阵来表示一个8x8的棋盘,'.'表示是空格,'P'表示人质,'K'表示骑士.每一步,骑士可以移动到他周围的8个方格中的任意一格.如果你移动到的格子中有人质(即'P'), ...

  2. BZOJ 1087: [SCOI2005]互不侵犯King [状压DP]

    1087: [SCOI2005]互不侵犯King Time Limit: 10 Sec  Memory Limit: 162 MBSubmit: 3336  Solved: 1936[Submit][ ...

  3. nefu1109 游戏争霸赛(状压dp)

    题目链接:http://acm.nefu.edu.cn/JudgeOnline/problemShow.php?problem_id=1109 //我们校赛的一个题,状压dp,还在的人用1表示,被淘汰 ...

  4. poj3311 TSP经典状压dp(Traveling Saleman Problem)

    题目链接:http://poj.org/problem?id=3311 题意:一个人到一些地方送披萨,要求找到一条路径能够遍历每一个城市后返回出发点,并且路径距离最短.最后输出最短距离即可.注意:每一 ...

  5. [NOIP2016]愤怒的小鸟 D2 T3 状压DP

    [NOIP2016]愤怒的小鸟 D2 T3 Description Kiana最近沉迷于一款神奇的游戏无法自拔. 简单来说,这款游戏是在一个平面上进行的. 有一架弹弓位于(0,0)处,每次Kiana可 ...

  6. 【BZOJ2073】[POI2004]PRZ 状压DP

    [BZOJ2073][POI2004]PRZ Description 一只队伍在爬山时碰到了雪崩,他们在逃跑时遇到了一座桥,他们要尽快的过桥. 桥已经很旧了, 所以它不能承受太重的东西. 任何时候队伍 ...

  7. bzoj3380: [Usaco2004 Open]Cave Cows 1 洞穴里的牛之一(spfa+状压DP)

    数据最多14个有宝藏的地方,所以可以想到用状压dp 可以先预处理出每个i到j的路径中最小权值的最大值dis[i][j] 本来想用Floyd写,无奈太弱调不出来..后来改用spfa 然后进行dp,这基本 ...

  8. HDU 1074 Doing Homework (状压dp)

    题意:给你N(<=15)个作业,每个作业有最晚提交时间与需要做的时间,每次只能做一个作业,每个作业超出最晚提交时间一天扣一分 求出扣的最小分数,并输出做作业的顺序.如果有多个最小分数一样的话,则 ...

  9. 【BZOJ1688】[Usaco2005 Open]Disease Manangement 疾病管理 状压DP

    [BZOJ1688][Usaco2005 Open]Disease Manangement 疾病管理 Description Alas! A set of D (1 <= D <= 15) ...

随机推荐

  1. Javascript的map与forEach的区别

    原理: 高级浏览器支持forEach方法语法:forEach和map都支持2个参数:一个是回调函数(item,index,list)和上下文: forEach:用来遍历数组中的每一项:这个方法执行是没 ...

  2. Thymeleaf基础知识

    Thymeleaf是一个Java类库,它是一个xml/xhtml/html5的模板引擎,可以作为MVC的Web引用的View层. Thymeleaf还提供了额外的模块与SpringMVC集成,因此推荐 ...

  3. 【Microsoft Azure学习之旅】测试消息队列(Service Bus Queue)是否会丢消息

    组里最近遇到一个问题,微软的Azure Service Bus Queue是否可靠?是否会出现丢失消息的情况? 具体缘由如下, 由于开发的产品是SaaS产品,为防止消息丢失,跨Module消息传递使用 ...

  4. Tomcat启动报Error listenerStart错误 | "beans" 必须匹配 DOCTYPE 根 "null" | java.lang.reflect.MalformedParameterizedTypeException

    maven打包发布工程时,发布上去却报错FAIL - Deployed application at context path /ch but context failed to start 在服务器 ...

  5. 算法练习-Palindrome Number

    判断回文整数 来源 https://leetcode.com/problems/palindrome-number/ 要求 判断一个整数是不是回文数,尽量减少内存暂用. 思路 可能的情况: 负数的应当 ...

  6. vos对接时业务确认及信息安全责任承诺书

           业务确认及信息安全责任承诺书 双方达成一致,******网络科技有限公司向            有限公司提供中国移动网内语音线路接入服务,保证资源长期使用,保证线路资源接通率标 准,合 ...

  7. oracle-插入到数据库中为日期

    oracle中创建一个表,其中一个字段为date,当我们进行插入操作 create table xf_allsalestotal ( xf_txdate date not null, xf_store ...

  8. IIS7 http自动跳转到https(通过编辑Web.config实现)

    本文摘自:https://www.cnblogs.com/wxbug/p/7054972.html 1.下载安装URL重写模块:Microsoft URL Rewrite Module 32位:htt ...

  9. Selenium入门系列3 单个元素的定位方法

    UI自动化首先要识别对象,再操作对象,最后判定实际结果与预期结果是否一致. 这一节学习的是识别单个对象,webdriver提供了8种方式. <a id="idofa" cla ...

  10. 【PHP 基础类库】Prototype 原型版教学文章!

    前言 大家好我是:石不易,今天我为大家带来了PHP基础类库原型版的教学文章,至此本人的作品线已分为三大类,分别是:JavaScript前端框架(封装库).PHP模板引擎.以及PHP基础类库.该类库历时 ...