HUD 1043 Eight 八数码问题 A*算法 1667 The Rotation Game IDA*算法
先是这周是搜索的题,网站:http://acm.hdu.edu.cn/webcontest/contest_show.php?cid=6041
主要内容是BFS,A*,IDA*,还有一道K短路的,.....木做,本来1009是说要用迭代加深做,但是我在他讲之前就用BFSA了,虽然很耗时,但还是过了,10000MS的时限,我8000+MS.......
1001 Eight 八数码问题
先把代码放上来
题目网址: http://acm.hdu.edu.cn/showproblem.php?pid=1043
500MS | 3524K | 3183 B |
#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<queue>
using namespace std;
class Node
{
public:
int maze[][]; //八数码具体情况
int h,g; //两个估价函数
int x,y; //空位的位置
int Hash; //HASH值
bool operator<(const Node n1)const{ //优先队列第一关键字为h,第二关键字为g
return h!=n1.h?h>n1.h:g>n1.g;
}
bool check() //判断是否合法
{
if(x>=&&x<&&y>=&&y<)
return true;
return false;
}
}s,u,v;
int HASH[]={,,,,,,,,}; //HASH的权值
int des=; //目标情况的HASH值
int vis[]; //判断状态已遍历,初始为-1,否则为到达这步的转向
int pre[]; //路径父节点
int way[][]={{,},{,-},{,},{-,}}; //四个方向
int get_hash(Node tmp) //获得HASH值
{
int a[],k=;
for(int i=;i<;i++)
for(int j=;j<;j++)
a[k++]=tmp.maze[i][j];
int res=;
for(int i=;i<;i++){
int k=;
for(int j=;j<i;j++)
if(a[j]>a[i])
k++;
res+=HASH[i]*k;
}
return res;
}
bool isok(Node tmp){ //求出逆序对,判断是否有解
int a[],k=;
for(int i=;i<;i++)
for(int j=;j<;j++)
a[k++]=tmp.maze[i][j];
int sum=;
for(int i=;i<;i++)
for(int j=i+;j<;j++)
if(a[j]&&a[i]&&a[i]>a[j])
sum++;
return !(sum&); //由于目标解为偶数,所以状态的逆序数为偶数才可行
}
int get_h(Node tmp){ //获得估价函数H
int ans=;
for(int i=;i<;i++)
for(int j=;j<;j++)
if(tmp.maze[i][j])
ans+=abs(i-(tmp.maze[i][j]-)/)+abs(j-(tmp.maze[i][j]-)%);
return ans;
}
void astar(){ //搜索
priority_queue<Node>que; //优先队列
que.push(s);
while(!que.empty())
{
u=que.top();
que.pop(); //出队
for(int i=;i<;i++)
{
v=u;
v.x+=way[i][];
v.y+=way[i][];
if(v.check())
{
swap(v.maze[v.x][v.y],v.maze[u.x][u.y]); //将空位和相邻位交换
v.Hash=get_hash(v); //得到HASH值
if(vis[v.Hash]==-)//判断是否已遍历且是否可行
{
vis[v.Hash]=i; //保存方向
v.g++;; //代价++
pre[v.Hash]=u.Hash; //保存v的父节点u
v.h=get_h(v); //得到新的估价函数H
que.push(v); //入队
}
if(v.Hash==des)
return ;
}
}
}
}
void print()
{
string ans;
char wu[]={'r','l','d','u'};
ans.clear();
int nxt=des;
while(pre[nxt]!=-) //从终点往起点找路径
{
ans+=wu[vis[nxt]];
nxt=pre[nxt]; //上一个父节点
}
for(int i=ans.size()-;i>=;i--)
printf("%c",ans[i]);
printf("\n");
}
int main()
{
char str[];
while(gets(str)!=NULL)
{
int k=;
memset(vis,-,sizeof(vis));
memset(pre,-,sizeof(pre));
for(int i=;i<;i++)
for(int j=;j<;j++)
{
if((str[k]<=''&&str[k]>='')||str[k]=='x')
{
if(str[k]=='x')
{
s.maze[i][j]=;
s.x=i;
s.y=j;
}
else
s.maze[i][j]=str[k]-'';
}
else
j--;
k++;
}
if(!isok(s)) //起始状态不可行
{
printf("unsolvable\n");
continue;
}
s.Hash=get_hash(s);
if(s.Hash==des)
{
printf("\n");
continue;
}
vis[s.Hash]=-;
s.g=;s.h=get_h(s);
astar(); //A*
print(); //打印路径
}
return ;
}
#include <iostream>
#include <stdio.h>
#include <string.h>
#include <string>
#include <algorithm>
#include <queue>
using namespace std;
class A
{
public:
int a[][];
int h,g;
int x,y;
int has;
bool operator<(const A n)const{return h!=n.h?h>n.h:g>n.g;}
bool check()
{
if (x>=&&x<=&&y>=&&y<=)
return true;
return false;
}
}s,w,r;
int H[]={,,,,,,,,};
int des=;
int v[];
int p[];
int d[][]={{,},{,-},{,},{-,}}; bool ok(A c)
{
int q[],k=,i,j,sum=;
for(i=;i<;i++)
for(j=;j<;j++)
q[k++]=c.a[i][j];
for(i=;i<;i++)
for(j=i+;j<;j++)
if(q[j]&&q[i]&&q[i]>q[j])
sum++;
return !(sum&);
} int gethas(A c)
{
int q[],k=,i,j,sum=;
for(i=;i<;i++)
for(j=;j<;j++)
q[k++]=c.a[i][j];
for(i=;i<;i++)
{
int o=;
for(j=;j<i;j++)
if(q[j]>q[i])
o++;
sum+=H[i]*o;
}
return sum;
} int geth(A c)
{
int sum=,i,j;
for(i=;i<;i++)
for(j=;j<;j++)
if(c.a[i][j])
sum+=abs(i-(c.a[i][j]-)/)+abs(j-(c.a[i][j]-)%);
return sum;
} void astar()
{
int i;
priority_queue<A>f;
f.push(s);
while(!f.empty())
{
w=f.top();
f.pop();
for(i=;i<;i++)
{
r=w;
r.x+=d[i][];
r.y+=d[i][];
if(r.check())
{
swap(r.a[w.x][w.y],r.a[r.x][r.y]);
r.has=gethas(r);
if(v[r.has]==-)
{
v[r.has]=i;
r.g++;
p[r.has]=w.has;
r.h=geth(r);
f.push(r);
}
if(r.has==des)
return ;
}
}
}
} void print()
{
string str;
char wu[]={'r','l','d','u'};
str.clear();
int next=des,i;
while(p[next]!=-)
{
str+=wu[v[next]];
next=p[next];
}
for(i=str.size()-;i>=;i--)
putchar(str[i]);
printf("\n");
} int main()
{
char b[];
int i,j,k;
while(gets(b)!=NULL)
{
memset(v,-,sizeof(v));
memset(p,-,sizeof(p));
k=;
for(i=;i<;i++)
for(j=;j<;j++)
{
if(b[k]=='x')
{
s.a[i][j]=;
s.x=i;
s.y=j;
}
else if(b[k]>=''&&b[k]<='')
s.a[i][j]=b[k]-'';
else
j--;
k++;
} if(!ok(s))
{
printf("unsolvable\n");
continue;
}
s.has=gethas(s);
if(s.has==des)
{
printf("\n");
continue;
}
v[s.has]=-;
s.g=;
s.h=geth(s);
astar();
print();
}
}
1006 The Rotation Game
第二题 IDA*算法,感觉比上面那个简单
题目网址:http://acm.hdu.edu.cn/showproblem.php?pid=1667
296MS | 300K | 1895 B |
#include <stdio.h>
#include <iostream>
#include <string.h>
#include <algorithm>
using namespace std;
int maxx(int x,int y,int z) {return max(max(x,y),z);} //三个数的最大值
int a[][]={
,,,,,,,,
,,,,,,,,
,,,,,,,,
,,,,,,,,
,,,,,,,,
,,,,,,,,
,,,,,,,,
,,,,,,,,
,,,,,,,
}; //每一纵行和横行的编号
int re[]={,,,,,,,,}; //往回移对应的编号
int mid[]={,,,,,,,,}; //中间的8个数的编号
char lu[]="OABCDEFGH"; //路径
int b[]; //现状
char father[]; //记录父节点的编号
int dep; //允许的深度 int geth(int b[]) //获得H值
{
int i,w[];
memset(w,,sizeof(w));
for(i=;i<=;i++)
w[b[mid[i]]]++;
return -maxx(w[],w[],w[]);
} int IDA(int g)
{
int i,H,t,j;
if(g>=dep)
return ;
for(i=;i<=;i++)
{
t=b[a[i][]];
for(j=;j<=;j++)
b[a[i][j]]=b[a[i][j+]];
b[a[i][]]=t;
father[g]=i; //记录父节点
H=geth(b); //获得最新的H
if(!H)
return ;
if(g+H<dep && IDA(g+)) //A*剪枝
return ;
t=b[a[re[i]][]]; //回到上一步
for(j=;j<=;j++)
b[a[re[i]][j]]=b[a[re[i]][j+]];
b[a[re[i]][]]=t;
}
return ;
} int main()
{
int i;
while(~scanf("%d",&b[])&&b[])
{
for(i=;i<=;i++)
scanf("%d",&b[i]);
dep=geth(b);
if(!dep) //不需要移动
{
printf("No moves needed\n");
printf("%d\n",b[]);
continue;
}
while(!IDA())
dep++;
for(i=;i<=dep-;i++)
printf("%c",lu[father[i]]);
printf("\n%d\n",b[]);
}
return ;
}
HUD 1043 Eight 八数码问题 A*算法 1667 The Rotation Game IDA*算法的更多相关文章
- HDU 1043 Eight 八数码问题 A*算法(经典问题)
HDU 1043 Eight 八数码问题(经典问题) 题意 经典问题,就不再进行解释了. 这里主要是给你一个状态,然后要你求其到达\(1,2,3,4,5,6,7,8,x\)的转移路径. 解题思路 这里 ...
- Hdu 1043 Eight (八数码问题)
题目链接: http://acm.hdu.edu.cn/showproblem.php?pid=1043 题目描述: 3*3的格子,填有1到8,8个数字,还有一个x,x可以上下左右移动,问最终能否移动 ...
- HDU-1043 Eight八数码 搜索问题(bfs+hash 打表 IDA* 等)
题目链接 https://vjudge.net/problem/HDU-1043 经典的八数码问题,学过算法的老哥都会拿它练搜索 题意: 给出每行一组的数据,每组数据代表3*3的八数码表,要求程序复原 ...
- hdu 1043 Eight (八数码问题)【BFS】+【康拓展开】
<题目链接> 题目大意:给出一个3×3的矩阵(包含1-8数字和一个字母x),经过一些移动格子上的数后得到连续的1-8,最后一格是x,要求最小移动步数. 解题分析:本题用BFS来寻找路径,为 ...
- A*算法 -- 八数码问题和传教士过河问题的代码实现
前段时间人工智能的课介绍到A*算法,于是便去了解了一下,然后试着用这个算法去解决经典的八数码问题,一开始写用了挺久时间的,后来试着把算法的框架抽离出来,编写成一个通用的算法模板,这样子如果以后需要用到 ...
- hdu 1043 Eight 经典八数码问题
题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=1043 The 15-puzzle has been around for over 100 years ...
- A*算法解决八数码问题 Java语言实现
0X00 定义 首先要明确一下什么是A*算法和八数码问题? A*(A-Star)算法是一种静态路网中求解最短路径最有效的直接搜索方法也是一种启发性的算法,也是解决许多搜索问题的有效算法.算法中的距离估 ...
- HDU 1043 Eight(八数码)
HDU 1043 Eight(八数码) 00 MS (Java/Others) Memory Limit: 65536/32768 K (Java/Others) Problem Descr ...
- Eight POJ - 1077 HDU - 1043 八数码
Eight POJ - 1077 HDU - 1043 八数码问题.用hash(康托展开)判重 bfs(TLE) #include<cstdio> #include<iostream ...
随机推荐
- Hibernate的表之间的关系
表:A.B 一对多关系:A中的一个字段的记录(主键)引用B中的多个记录(外键) 多对一关系:A中的一个字段的记录(外键)引用B中的一个记录(主键) 一对一关系:A.B两个表的关联字段都是主键 多对多关 ...
- redis简介及常见问题
目录 简介 特点 优点 高性能 高并发 为什么要用 redis 而不用 map/guava 做缓存? redis 和 memcached 的区别 Redis快的原因 为什么redis是单线程 为什么r ...
- golang——字符串与编码
1.字符编码 (1)ASCII码 一个字节表示的英文.数字.标点符号等字符. 国际标准ASCII码为0-127即128个字符,二进制最高位为0,其余为扩展ASCII码. (2)GB2312 两字节,主 ...
- 自己编写的str操作函数
1.strcat() 此函数原型为 char *strcat(char *dest, const char *src). 功能为连接两个字符串,把src连接到dest后面:返回dest地址 实现如下 ...
- [转]C语言字符串操作总结大全(超详细)
1)字符串操作 strcpy(p, p1) 复制字符串 strncpy(p, p1, n) 复制指定长度字符串 strcat(p, p1) 附加字符串 strncat(p, p1, n) 附加指定长度 ...
- ACM_Appleman and Card Game(简单贪心)
Appleman and Card Game Time Limit: 2000/1000ms (Java/Others) Problem Description: Appleman has n car ...
- 【转】MySQL常见的运算符及使用
转自:http://www.linuxidc.com/Linux/2016-03/129672.htm MySQL中有4类运算符,它们是: 算术运算符 比较运算符 逻辑运算符 位操作运算符 算术操作符 ...
- 2199. [HZOI 2016] 活动投票
★★ 输入文件:hztp.in 输出文件:hztp.out 简单对比 时间限制:0.5 s 内存限制:2 MB [题目描述] 衡中活动很多,人也很多,一次活动有n个学生参与投票,现已知 ...
- 【译】x86程序员手册28-7.7任务地址空间
7.7 Task Address Space 任务地址空间 The LDT selector and PDBR fields of the TSS give software systems desi ...
- DataWhale学习计划(第六期):python基础任务6
file-settings 然后选择project Interpreter 把project Interpreter复选框里面的地址换成你安装的anaconda下的python.exe的地址,点击sh ...