题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=6171

题意: 给你一个高度为6的塔形数组,你每次只能将0与他上下相邻的某个数交换,问最少交换多少次可以变为初始状态,若需要的步数大于20,直接输出too difficult,初始状态为:


1 1 
2 2 2 
3 3 3 3 
4 4 4 4 4 
5 5 5 5 5 5

解法:两种方法,一种是双向BFS+Hash,另外是A*估价+Hash。

双向搜索参考:http://blog.csdn.net/cillyb/article/details/77587228

//双BFS
#include <bits/stdc++.h>
using namespace std;
const int maxn = 100010;
const int dir[4][2] = {{-1,-1},{-1,0},{1,0},{1,1}};
typedef unsigned long long uLL;
struct node{
int val[6][6];
int r, c, k, step;
};
map <uLL, int> book[2];
uLL Hash(node x){
uLL ret = 0;
for(int i=0; i<6; i++)
for(int j=0; j<=i; j++)
ret = ret*6+x.val[i][j];
return ret;
}
int BFS(node s, node e){
queue <node> q;
book[0].clear();
book[1].clear();
s.k = 0;
e.k = 1;
s.step = e.step = 0;
book[s.k][Hash(s)] = 0;
book[e.k][Hash(e)] = 0;
q.push(s);
q.push(e);
while(q.size()){
node u = q.front(); q.pop();
uLL tmp = Hash(u);
if(book[!u.k].count(tmp)){
if(book[!u.k][tmp]+u.step<=20){
return book[!u.k][tmp]+u.step;
}
else continue;
}
if(u.step >= 10) continue;
for(int i=0; i<4; i++){
node t = u;
t.r += dir[i][0];
t.c += dir[i][1];
if(t.r >= 6 || t.r < 0 || t.c > t.r || t.c < 0) continue;
swap(t.val[t.r][t.c], t.val[u.r][u.c]);
tmp = Hash(t);
if(book[t.k].count(tmp)) continue;
t.step++;
book[t.k][tmp] = t.step;
q.push(t);
}
}
return -1;
}
int main()
{
int T;
scanf("%d", &T);
while(T--)
{
node s,e;
e.r = e.c = 0;
for(int i=0; i<6; i++){
for(int j=0; j<=i; j++){
scanf("%d", &s.val[i][j]);
if(!s.val[i][j])
s.r = i, s.c = j;
e.val[i][j] = i;
}
}
int ans = BFS(s, e);
if(ans == -1) puts("too difficult");
else printf("%d\n", ans);
}
return 0;
}

放一个队友的A*搜索:

#include<bits/stdc++.h>
using namespace std;
typedef unsigned long long uLL;
int lowPos[6][6];
pair<int, int> ppPos[22];
const int dir[4][2] = {{-1, -1}, {-1, 0}, {1, 0}, {1, 1}};
void init()
{
int jsq = 0;
int now = 0;
for(int i = 0; i < 6; i++)
for(int j = 0; j <= i; j++)
{
lowPos[i][j] = now;
ppPos[jsq] = make_pair(i, j);
jsq ++;
now += 3;
}
}
void setStatus(uLL &status, int x, int y, uLL val)
{
int pos = lowPos[x][y];
status &= ~(1ULL << pos);
status &= ~(1ULL << pos + 1);
status &= ~(1ULL << pos + 2);
status |= val << pos;
return;
}
void swapStatus(uLL &status, int a, int b, int x, int y)
{
int pos1 = lowPos[a][b];
int pos2 = lowPos[x][y];
uLL val1 = status >> pos1 & 7;
uLL val2 = status >> pos2 & 7;
status &= ~(1ULL << pos1);
status &= ~(1ULL << pos1 + 1);
status &= ~(1ULL << pos1 + 2);
status &= ~(1ULL << pos2);
status &= ~(1ULL << pos2 + 1);
status &= ~(1ULL << pos2 + 2);
status |= val1 << pos2;
status |= val2 << pos1;
}
pair<int, int> getZeroPos(uLL status)
{
for(int i = 0; i < 21; i++)
{
uLL val = status & 7;
if(val == 0)
return ppPos[i];
status >>= 3;
}
}
int Compare(uLL endStatus, uLL nowStatus)
{
int ret = 0;
for(int i = 0; i < 21; i++)
{
uLL val1 = endStatus & 7;
uLL val2 = nowStatus & 7;
if(val1 != val2)
ret++;
endStatus >>= 3;
nowStatus >>= 3;
}
return ret;
}
int main()
{
init();
int T;
scanf("%d", &T);
while(T--)
{
uLL startStatus = 0;
for(int i = 0; i < 6; i++)
for(int j = 0; j <= i; j++)
{
int x;
scanf("%d", &x);
setStatus(startStatus, i, j, x);
}
uLL endStatus = 0;
for(int i = 0; i < 6; i++)
for(int j = 0; j <= i; j++)
setStatus(endStatus, i, j, i);
queue<uLL> q;
unordered_map<uLL, int> mp;
mp[startStatus] = 0;
q.emplace(startStatus);
while(!q.empty())
{
uLL u = q.front();
q.pop();
if(u == endStatus)
break;
int d = mp[u];
if(d == 20)
break;
pair<int, int> zpos = getZeroPos(u);
int i = zpos.first;
int j = zpos.second;
for(int k = 0; k < 4; k++)
{
int x = i + dir[k][0];
int y = j + dir[k][1];
if(x < 0 || x > 5 || y < 0 || y > x)
continue;
uLL newStatus = u;
swapStatus(newStatus, i, j, x, y);
if(mp.count(newStatus))
continue;
mp[newStatus] = d + 1;
int famly = Compare(endStatus, newStatus);
if(famly + d + 2 > 20)
continue;
q.emplace(newStatus);
}
}
if(mp.count(endStatus) == 0)
puts("too difficult");
else
printf("%d\n", mp[endStatus]);
}
return 0;
}

2017多校第10场 HDU 6171 Admiral 双向BFS或者A*搜索的更多相关文章

  1. 2017多校第10场 HDU 6178 Monkeys 贪心,或者DP

    题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=6178 题意:给出一棵有n个节点的树,现在需要你把k只猴子放在节点上,每个节点最多放一只猴子,且要求每只 ...

  2. 2017多校第10场 HDU 6181 Two Paths 次短路

    题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=6181 题意:给一个图,求出次短路. 解法:我之前的模板不能解决这种图,就是最短路和次短路相等的情况,证 ...

  3. 2017多校第10场 HDU 6180 Schedule 贪心,multiset

    题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=6180 题意:给了一些任务的开始时间和终止时间,现在让我们安排k台及机器,让这些任务在k太机器上最小,并 ...

  4. 2017多校第10场 HDU 6172 Array Challenge 猜公式,矩阵幂

    题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=6172 题意:如题. 解法: #include <bits/stdc++.h> using ...

  5. 2017多校第9场 HDU 6161 Big binary tree 思维,类似字典树

    题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=6161 题意: 题目是给一棵完全二叉树,从上到下从左到右给每个节点标号,每个点有权值,初始权值为其标号, ...

  6. 2017多校第9场 HDU 6169 Senior PanⅡ 数论,DP,爆搜

    题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=6169 题意:给了区间L,R,求[L,R]区间所有满足其最小质数因子为k的数的和. 解法: 我看了这篇b ...

  7. 2017多校第8场 HDU 6138 Fleet of the Eternal Throne AC自动机或者KMP

    题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=6138 题意:给n个串,每次询问x号串和y号串的最长公共子串的长度,这个子串必须是n个串中某个串的前缀 ...

  8. 2017多校第8场 HDU 6134 Battlestation Operational 莫比乌斯反演

    题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=6134 题意: 解法: 那么g(n)怎么求,我们尝试打表发现g(n)是有规律的,g(n)=g(n-1)+ ...

  9. 2017多校第7场 HDU 6129 Just do it 找规律

    题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=6129 题意:求a序列后m次xor前缀和 解法: 手动对1位置对每个位置的贡献打表发现 第一次 贡献为 ...

随机推荐

  1. nodejs 全局变量和全局对象

    1.全局对象 所有模块都可以调用 1)global:表示Node所在的全局环境,类似于浏览器中的window对象. 2)process:指向Node内置的process模块,允许开发者与当前进程互动. ...

  2. Python基础之字符编码

    前言 字符编码非常容易出问题,我们要牢记几句话: 1.用什么编码保存的,就要用什么编码打开 2.程序的执行,是先将文件读入内存中 3.unicode是父编码,只能encode解码成其他编码格式 utf ...

  3. 【CSS】伪类与伪元素

    一伪类 语法: selector : pseudo-class {property: value} 提示:伪类名称对大小写不敏感.    与 CSS类搭配使用 selector.class : pse ...

  4. echarts添加点击事件

    由于工作需要,需要用echarts 进行展示图表,却又个新的需求,要点击展示的地方,同时下面出现table展示内容 如图所示: 一开始找了好多博客,发现都不好用,大部分都是用到了 var ecConf ...

  5. Android学习笔记-App初始启动界面实现

    android手机上的很多应用程序启动时都会先显示一个图片,作为该应用程序的开始,该图片转瞬即逝.这个图片一般都会用应用的图标,作为广告来用. 例如: 它的实现方式很简单,我们以一个测试APP为例,介 ...

  6. elk 5.x的部署

    前言 elk是由elasticsearch.logstash.kibana三者组成 其中elasticsearch主要负责数据存储与搜索 logstash主要负责收集日志信息以及对日志信息的切片索引等 ...

  7. 利用Apache commons-net 包进行FTP文件和文件夹的上传与下载

    首先声明:这段代码是我在网上胡乱找的,调试后可用. 需要提前导入jar包,我导入的是:commons-net-3.0.1,在网上可以下载到.以下为源码,其中文件夹的下载存在问题:FTPFile[] a ...

  8. JavaScript字符串处理

    字符串处理 1.连接字符串: 1)连接符+: 2)连接赋值+=: 3)连接函concat() 2.查找子串位置indexOf() 1)在指定字符串中是否存在给定的字符串(第一次出现) 2)用法str. ...

  9. 压缩[SCOI2007]

    题目描述 给一个由小写字母组成的字符串,我们可以用一种简单的方法来压缩其中的重复信息.压缩后的字符串除了小写字母外还可以(但不必)包含大写字母R与M,其中M标记重复串的开始,R重复从上一个M(如果当前 ...

  10. nodejs01--什么是nodejs,nodejs的基本使用

    nodejs使用范围 -直接在cmd命令行运行,在你的电脑上直接运行 -可以搭建一个web服务器(express,koa) -一些基本的使用 -modules是如何工作的 -npm管理modules ...