POJ 1077 HDU 1043 Eight (IDA*)
题意就不用再说明了吧......如此经典
之前想用双向广搜、a*来写,但总觉得无力,现在用IDA*感觉其他的解法都弱爆了..............想法活跃,时间,空间消耗很小,给它跪了
启发式搜索关键还是找估价函数:此题估价函数可大致定性为每个数字(除去x,只要8个数字)当前位置与它期望位置的曼哈顿距离
即为:v += abs(i - pos[map[i][j] - 1][0]); v += abs(j - pos[map[i][j] - 1][1]); 大致估算为几十步内得出结果。
#include <iostream>
#include <algorithm>
#include <cmath>
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <string>
#include <vector>
#include <set>
#include <queue>
#include <stack>
#include <climits>//形如INT_MAX一类的
#define MAX 100005
#define INF 0x7FFFFFFF
#define REP(i,s,t) for(int i=(s);i<=(t);++i)
#define ll long long
#define mem(a,b) memset(a,b,sizeof(a))
#define mp(a,b) make_pair(a,b)
#define L(x) x<<1
#define R(x) x<<1|1
# define eps 1e-5
//#pragma comment(linker, "/STACK:36777216") ///传说中的外挂
using namespace std; int pos[9][2] = { //各个数字的初始位置
{0,0},{0,1},{0,2},
{1,0},{1,1},{1,2},
{2,0},{2,1},{2,2}
};
int map[4][4];
int buff[50];
char input[11];
int limit,ok;
int dx[] = {-1,0,1,0}; //u r d l____0 1 2 3
int dy[] = {0,1,0,-1};
char op[] = {'u','r','d','l'}; int h(int x,int y) {
int v = 0;
for(int i=0; i<3; i++) {
for(int j=0; j<3; j++) {
if(i != x || j != y) {
v += abs(i - pos[map[i][j] - 1][0]);
v += abs(j - pos[map[i][j] - 1][1]);
}
}
}
return v;
} int dfs(int x,int y,int step,int pre) {
int hn = h(x,y);
if(hn == 0) {
ok = 1;
return step;
}
if(hn + step > limit) return hn + step;
int minn = INF;
for(int i=0; i<4; i++) {
if(abs(i - pre) == 2) continue;
int xx = x + dx[i];
int yy = y + dy[i];
if(xx<0 || xx >=3 || yy<0 || yy >=3) continue;
buff[step] = i;
swap(map[x][y],map[xx][yy]);
int tmp = dfs(xx,yy,step+1,i);
if(ok) return tmp;
minn = min(tmp,minn);
swap(map[x][y],map[xx][yy]);
}
return minn;
} void IDA_star(int x,int y) {
ok = 0;
memset(buff,-1,sizeof(buff));
while(ok == 0 && limit <= 36) {
limit = dfs(x,y,0,-111);
}
if(ok == 1) {
for(int i=0; i<limit; i++) printf("%c",op[buff[i]]);
puts("");
} else puts("unsolvable");
} int main() {
for(int i=0; i<9; i++) cin >> input[i];
int t = 0,x,y;
for(int i=0; i<3; i++) {
for(int j=0; j<3; j++) {
if(input[t] == 'x') {
map[i][j] = 9;
x = i;
y = j;
t++;
} else map[i][j] = input[t++] - '0';
}
}
int limit = h(x,y);
if(limit == 0) {
puts("");
return 0;
}
IDA_star(x,y);
return 0;
}
想吐槽一下杭电的这题.........估计各种无法到达目标的数据,所以在输入时候通过求逆序数对数来判断是否有解,本来是TLE,一下蹦到171ms
#include <iostream>
#include <algorithm>
#include <cmath>
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <string>
#include <vector>
#include <set>
#include <queue>
#include <stack>
#include <climits>//形如INT_MAX一类的
#define MAX 100005
#define INF 0x7FFFFFFF
#define REP(i,s,t) for(int i=(s);i<=(t);++i)
#define ll long long
#define mem(a,b) memset(a,b,sizeof(a))
#define mp(a,b) make_pair(a,b)
#define L(x) x<<1
#define R(x) x<<1|1
# define eps 1e-5
//#pragma comment(linker, "/STACK:36777216") ///传说中的外挂
using namespace std; int pos[9][2] = { //各个数字的初始位置
{0,0},{0,1},{0,2},
{1,0},{1,1},{1,2},
{2,0},{2,1},{2,2}
};
int map[4][4];
int buff[50];
char input[11];
int limit,ok;
int dx[] = {-1,0,1,0}; //u r d l____0 1 2 3
int dy[] = {0,1,0,-1};
char op[] = {'u','r','d','l'}; int h(int x,int y) {
int v = 0;
for(int i=0; i<3; i++) {
for(int j=0; j<3; j++) {
if(i != x || j != y) {
v += abs(i - pos[map[i][j] - 1][0]);
v += abs(j - pos[map[i][j] - 1][1]);
}
}
}
return v;
} int dfs(int x,int y,int step,int pre) {
int hn = h(x,y);
if(hn == 0) {
ok = 1;
return step;
}
if(hn + step > limit) return hn + step;
int minn = INF;
for(int i=0; i<4; i++) {
if(abs(i - pre) == 2) continue;
int xx = x + dx[i];
int yy = y + dy[i];
if(xx<0 || xx >=3 || yy<0 || yy >=3) continue;
buff[step] = i;
swap(map[x][y],map[xx][yy]);
int tmp = dfs(xx,yy,step+1,i);
if(ok) return tmp;
minn = min(tmp,minn);
swap(map[x][y],map[xx][yy]);
}
return minn;
}
int canget(int a[4][4]) { //这一步省了好多时间 求逆序数对数
int i,j,sum=0,b[10],k=0;
for(i=0; i<3; i++) {
for(j=0; j<3; j++) {
if(a[i][j] != 9)
b[++k]=a[i][j];
}
}
for(i=1; i<=8; i++) {
for(j=1; j<i; j++) {
if(b[i]<b[j])sum++;
}
}
if(sum % 2 ==0)return 1;
else return 0;
}
void IDA_star(int x,int y) {
ok = 0;
memset(buff,-1,sizeof(buff));
while(ok == 0 && limit <= 30) {
limit = dfs(x,y,0,-111);
}
if(ok == 1) {
for(int i=0; i<limit; i++) printf("%c",op[buff[i]]);
puts("");
} else puts("unsolvable");
} int main() {
while(cin >> input[0]) {
//memset(map,0,sizeof(map));
for(int i=1; i<9; i++) cin >> input[i];
int t = 0,x,y;
for(int i=0; i<3; i++) {
for(int j=0; j<3; j++) {
if(input[t] == 'x') {
map[i][j] = 9;
x = i;
y = j;
t++;
} else map[i][j] = input[t++] - '0';
}
}
limit = h(x,y);
if(limit == 0) {
puts("");
continue;
}
if(canget(map))
IDA_star(x,y);
else puts("unsolvable");
}
return 0;
}
经过猥琐的测试,limit最小限制在29步....................
POJ 1077 HDU 1043 Eight (IDA*)的更多相关文章
- Eight POJ - 1077 HDU - 1043 八数码
Eight POJ - 1077 HDU - 1043 八数码问题.用hash(康托展开)判重 bfs(TLE) #include<cstdio> #include<iostream ...
- POJ 1077 && HDU 1043 Eight A*算法,bfs,康托展开,hash 难度:3
http://poj.org/problem?id=1077 http://acm.hdu.edu.cn/showproblem.php?pid=1043 X=a[n]*(n-1)!+a[n-1]*( ...
- BFS(八数码) POJ 1077 || HDOJ 1043 Eight
题目传送门1 2 题意:从无序到有序移动的方案,即最后成1 2 3 4 5 6 7 8 0 分析:八数码经典问题.POJ是一次,HDOJ是多次.因为康托展开还不会,也写不了什么,HDOJ需要从最后的状 ...
- HDU 1043 & POJ 1077 Eight(康托展开+BFS | IDA*)
Eight Time Limit: 1000MS Memory Limit: 65536K Total Submissions: 30176 Accepted: 13119 Special ...
- HDU 1043 & POJ 1077 Eight(康托展开+BFS+预处理)
Eight Time Limit: 1000MS Memory Limit: 65536K Total Submissions: 30176 Accepted: 13119 Special ...
- HDU - 1043 - Eight / POJ - 1077 - Eight
先上题目: Eight Time Limit: 10000/5000 MS (Java/Others) Memory Limit: 65536/32768 K (Java/Others)Tota ...
- HDU 1403 Eight&POJ 1077(康拖,A* ,BFS,双广)
Eight Time Limit: 10000/5000 MS (Java/Others) Memory Limit: 65536/32768 K (Java/Others) Total Submis ...
- POJ 2104&HDU 2665 Kth number(主席树入门+离散化)
K-th Number Time Limit: 20000MS Memory Limit: 65536K Total Submissions: 50247 Accepted: 17101 Ca ...
- POJ-1077 HDU 1043 HDU 3567 Eight (BFS预处理+康拓展开)
思路: 这三个题是一个比一个令人纠结呀. POJ-1077 爆搜可以过,94ms,注意不能用map就是了. #include<iostream> #include<stack> ...
随机推荐
- python 学习day5(模块)
一.模块介绍 模块,用一砣代码实现了某个功能的代码集合. 类似于函数式编程和面向过程编程,函数式编程则完成一个功能,其他代码用来调用即可,提供了代码的重用性和代码间的耦合.而对于一个复杂的功能来,可能 ...
- ubuntu_安装aptana3
下面记录下偶怎么安装aptana3(aptana2应该也适用). 安装java运行时,偷看这里 说明:实际上偶并没有执行这步,因为发现在安装aptana3之前 java的运行时已经安装过了. 貌似是安 ...
- WebView cookies清理
今天在项目中发现一个BUG 在使用新浪微博账户登录应用时,webview会自动登录上次的微博帐号!(因为webview 记录了微博帐号和密码的cookies) 所以,需要清除SessionCookie ...
- iOS学习,需要懂的一些基础
1. KVC 与 KVO 全称是Key-value coding,翻译成键值编码.顾名思义,在某种程度上跟map的关系匪浅.它提供了一种使用字符串而不是访问器方法去访问一个对象实例变量的机制. 全称 ...
- C# 使用XmlDocument类对XML文档进行操作
原创地址:http://www.cnblogs.com/jfzhu/archive/2012/11/19/2778098.html 转载请注明出处 W3C制定了XML DOM标准.很多编程语言中多提供 ...
- Android之TextView的样式类Span的使用具体解释
Android中的TextView是个显示文字的的UI类,在现实中的需求中,文字有各式各样的样式.TextView本身没有属性去设置实现,我们能够通过Android提供的 SpannableStrin ...
- Microsoft.Jet.OLEDB.4.0和Microsoft.ACE.OLEDB.12.0的适用版本
Jet 可以访问 Office 97-2003,但不能访问 Office 2007. ACE 既可以访问 Office 2007,也可以访问 Office 97-2003. 另外:Microsof ...
- trie tree(字典树)
hihocoder题目(http://hihocoder.com/problemset):#1014 trie树 #include <iostream> using namespace s ...
- C++ Primer 读书笔记: 第9章 顺序容器
第9章 顺序容器 引: 顺序容器: vector 支持快速随机访问 list 支持快速插入/删除 deque 双端队列 顺序容器适配器: stack 后进先出栈 queue 先进先出队列 priori ...
- leetcode Divide Two Integers python
class Solution(object): def divide(self, dividend, divisor): """ :type dividend: int ...