神奇密码锁 bfs
来源:互联网 发布:网络摄像机监控软件 编辑:程序博客网 时间:2024/06/05 11:29
问题 D: 神奇密码锁
时间限制: 2 Sec 内存限制: 128 MB提交: 204 解决: 53
[提交][状态][讨论版]
题目描述
小明忘记了旅行箱上的密码,现在他想自己暴力弄出密码来,但他又想知道最从一个数字到另一个数字最少需要多少步,现在请你帮忙。
另外,小明的密码箱很奇怪,只有四位数,上面的数字只有1到9,每次只能让每位数加1或者减1。按常识我们可以知道从1到9只需要减1,从9到1只需要加1。此外,你还能交换相邻的两个数字。如1234可以在一步后变成2134,但不能变成4231。
输入
第一行有一个整数:T,代表有多少组测试数据。
接下来T行,每行有两个整数(都是四位数),第一个是初状态,第二个是目标状态。
输出
每组数据输出一个整数,占一行。
样例输入
21234 21441111 9999
样例输出
24
提示
#include <iostream>#include <cstdio>#include <cstring>#include <queue>using namespace std;int st[6],goal[6];char st0[6],goal0[6];int visti[10000];int ans;struct data { int s[6]; int sum;};//queue <data> que;bool check(int s[]){ int t=(s[0])*1000+(s[1])*100+(s[2])*10+(s[3]); if(!visti[t]){ visti[t]=1;//标记为已访问 return true; } return false;}void bfs() { queue <data> que; data p; memcpy(p.s,st,sizeof(st)); p.sum=0; if(check(p.s)) que.push(p); while(!que.empty()) { p=que.front(); que.pop(); if(!memcmp(p.s,goal,sizeof(goal))) { ans=p.sum; return ; } for(int j=0; j<4; j++) { int t=p.s[j]; p.sum++; if(p.s[j]<9) p.s[j]++; else p.s[j]=1; if(check(p.s)) que.push(p); p.s[j]=t; if(p.s[j]>1) p.s[j]--; else p.s[j]=9; if(check(p.s)) que.push(p); p.s[j]=t; if(j<3) { int temp; temp=p.s[j+1]; p.s[j+1]=p.s[j]; p.s[j]=temp; if(check(p.s)) que.push(p); p.s[j]=t; p.s[j+1]=temp; } p.sum--; } }}int main() { int n; scanf("%d",&n); while(n--) { ans=0; scanf("%s%s",st0,goal0); for(int i=0;i<4;i++) { st[i]=st0[i]-'0'; goal[i]=goal0[i]-'0'; } memset(visti,0,sizeof(visti)); bfs(); printf("%d\n",ans); }}
下面的代码,想尝试用A*算法,写的,但是在求H(n)的函数那里找不到一个好的办法,所以导致超时了。留在这里日后思考。如果有路过的大神知道如何修改,可以私聊我。QQ:751479173
#include <iostream>#include <cstdio>#include <cstring>#include <queue>#include <math.h>#include <stdio.h>#include <stdlib.h>using namespace std;int st[6],goal[6];char st0[6],goal0[6];int visti[10000];int ans;struct data { int s[6]; int sum; int g,h,f; bool operator < (const data & k) const { //重载比较运算符 if(f==k.f) return g>k.g; return f > k.f; }};//queue <data> que;bool check(int s[]) { int t=(s[0])*1000+(s[1])*100+(s[2])*10+(s[3]); if(!visti[t]) { visti[t]=1;//标记为已访问 return true; } return false;}int bianhao(int s[]) { int t; return t=(s[0])*1000+(s[1])*100+(s[2])*10+(s[3]);}int wrongPlaceNum(int a[]) { //求不在位的数字个数 int cnt=0; for(int i=0; i<4; i++) if(a[i]!=goal[i]) cnt++; return cnt;}void bfs() { priority_queue <data> que; data p,q; memcpy(q.s,st,sizeof(st)); q.sum=p.g=0; q.h=wrongPlaceNum(q.s); q.f=q.g+q.h; if(check(q.s)) que.push(q); while(!que.empty()) { q=que.top(); que.pop(); if(!memcmp(q.s,goal,sizeof(goal))) { ans=q.sum; return ; } for(int j=0; j<4; j++) { memcpy(&p,&q,sizeof(q)); if(p.s[j]<9) p.s[j]++; else p.s[j]=1; if(check(p.s)) { p.g=p.g+1; p.h=wrongPlaceNum(p.s); p.f=p.g+p.h; p.sum++; que.push(p); } memcpy(&p,&q,sizeof(q)); if(p.s[j]>1) p.s[j]--; else p.s[j]=9; if(check(p.s)) { p.g=p.g+1; p.h=wrongPlaceNum(p.s); p.f=p.g+p.h; p.sum++; que.push(p); } memcpy(&p,&q,sizeof(q)); if(j<3) { int temp; temp=p.s[j+1]; p.s[j+1]=p.s[j]; p.s[j]=temp; if(check(p.s)) { p.g=p.g+1; p.h=wrongPlaceNum(p.s); p.f=p.g+p.h; p.sum++; que.push(p); } } memcpy(&p,&q,sizeof(q)); } }}int main() { int n; scanf("%d",&n); while(n--) { ans=0; scanf("%s%s",st0,goal0); for(int i=0; i<4; i++) { st[i]=st0[i]-'0'; goal[i]=goal0[i]-'0'; } memset(visti,0,sizeof(visti)); bfs(); printf("%d\n",ans); }}
阅读全文
0 0
- 神奇密码锁 bfs
- 神奇密码锁(BFS)
- 神奇密码锁 BFS (枚举) 进位转换 memcmp
- 神奇密码锁
- 神奇密码锁
- 问题 D: 神奇密码锁
- 搜索 问题 D: 神奇密码锁
- 密码锁
- 密码锁
- 算法提高 题目 2 密码锁 (bfs最少步数)
- HDU 4474(神奇的BFS+强剪枝)
- 电子密码锁
- 电子密码锁
- 简单密码锁
- 12864密码锁
- 动态密码锁
- 手势密码锁
- 密码锁问题
- nrf51822-提高nordic ble数据发送速率
- jtemplates setParam 简单用法
- Sass预编译语言之@mixin混合的几种声明和调用方式
- Ubuntu下安装Remix OS双系统
- AR项目的简单实现过程
- 神奇密码锁 bfs
- React Native项目建立
- JAVA虚拟机总结以看别人Blog理解
- Mac上相关安装和一些命令的使用
- HTML5常用表单验证
- bat命令模拟加载---巧用ping命令
- 《剑指offer》不用加减乘除做加法
- docker学习笔记(一)
- ubuntu16.04离线安装NIVIDIA驱动