HDU 1195 Open the Lock
2016-05-12 18:34
471 查看
题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=1195
题意:给两个四位数,并给出变化规则,求最少的变化次数将一个数变为另一个数。可以将每一位加一或者减一(1减一变为9,9加一变为1),或者交换相邻两位的数字。
思路:因为局限于四位数,所以状态很少可以直接bfs,只是状态转移略麻烦。这种简单的题目可以练习双向bfs。
单向bfs,注释见双向bfs代码
双向bfs
题意:给两个四位数,并给出变化规则,求最少的变化次数将一个数变为另一个数。可以将每一位加一或者减一(1减一变为9,9加一变为1),或者交换相邻两位的数字。
思路:因为局限于四位数,所以状态很少可以直接bfs,只是状态转移略麻烦。这种简单的题目可以练习双向bfs。
单向bfs,注释见双向bfs代码
#include <cstdio> #include <cmath> #include <cstring> #include <string> #include <cstdlib> #include <iostream> #include <algorithm> #include <stack> #include <map> #include <set> #include <vector> #include <sstream> #include <queue> #include <utility> using namespace std; #define rep(i,j,k) for (int i=j;i<=k;i++) #define Rrep(i,j,k) for (int i=j;i>=k;i--) #define Clean(x,y) memset(x,y,sizeof(x)) const int maxn = 10009; int T; int st,ed; int vis[maxn]; int step[maxn]; int q[maxn]; int f[5] = {0,1,10,100,1000}; void init() { scanf("%d %d",&st,&ed); Clean(vis,0); Clean(step,0); } void push(int st , int ed,int &tail) { if ( !vis[ed] ) { q[++tail] = ed; vis[ed] = 1; step[ed] = step[st] + 1; } } int bfs() { int head,tail,ans; head = tail = -1; q[++tail] = st; vis[st] = 1; int now,next; while(head<tail) { head++; now = q[head]; if ( now == ed ) return step[now]; int digit[5]; rep(i,1,4) digit[i] = now % 10,now /=10;; now = q[head]; rep(i,1,4) { next = now - f[i]; if ( digit[i] == 1 ) next+=9*f[i]; push(now,next,tail); next = now + f[i]; if ( digit[i] == 9 ) next-=9*f[i]; push(now,next,tail); } rep(i,1,3) { next = now + digit[i]*(f[i+1]-f[i]) - digit[i+1]*( f[i+1] - f[i] ); push(now,next,tail); } } return -1; } int main() { scanf("%d",&T); while(T--) { init(); printf("%d\n",bfs()); } return 0; }
双向bfs
#include <cstdio> #include <cmath> #include <cstring> #include <string> #include <cstdlib> #include <iostream> #include <algorithm> #include <stack> #include <map> #include <set> #include <vector> #include <sstream> #include <queue> #include <utility> using namespace std; #define rep(i,j,k) for (int i=j;i<=k;i++) #define Rrep(i,j,k) for (int i=j;i>=k;i--) #define Clean(x,y) memset(x,y,sizeof(x)) const int maxn = 10009; int T; int st,ed; int vis[maxn]; int step[maxn]; int q[maxn]; int f[5] = {0,1,10,100,1000}; //每一位的权值 void init() //初始化和读入 { scanf("%d %d",&st,&ed); Clean(vis,0); Clean(step,0); } int find(int st,int ed,int &tail) //由当前数st变到ed,判断是否搜索结束 { if ( !vis[ed] ) //ed没有出现过就入队 { vis[ed] = vis[st]; step[ed] = step[st] + 1; q[++tail] = ed; } else { if ( vis[st] != vis[ed] ) //正反搜索相遇,返回最短步数 return step[st] + step[ed] + 1; } return 0; } int bfs() { int head,tail,ans; head = tail = -1; q[++tail] = st; q[++tail] = ed; vis[st] = 1; vis[ed] = 2; int now,next; while(head<tail) { head++; now = q[head]; int digit[5]; rep(i,1,4) //将每一位分离出来 digit[i] = now % 10,now /=10;; now = q[head]; rep(i,1,4) //对于每一位进行加减 { next = now - f[i]; //减一 if ( digit[i] == 1 ) next+=9*f[i]; //如果该位为1,减去就变为9 if ( ans = find(now,next,tail) ) return ans; next = now + f[i]; //加一 if ( digit[i] == 9 ) next-=9*f[i]; if ( ans = find(now,next,tail) ) return ans; } rep(i,1,3) //第i位和第i+1位交换 { next = now + digit[i]*(f[i+1]-f[i]) - digit[i+1]*( f[i+1] - f[i] ); if ( ans = find(now,next,tail) ) return ans; } } return -1; //返回无解 不过不可能 } int main() { scanf("%d",&T); while(T--) { init(); printf("%d\n",bfs()); } return 0; }
相关文章推荐
- 关于OpenWRT编译的一些Mark
- centos下配置java环境变量
- 手游页游和端游的服务端的架构与区别
- Linux默认目录简介
- Nginx启动脚本
- Nginx负载均衡配置
- linux 文件上传&软件安装(rpm)
- Linux下后台挂起和杀死进程
- 合并CentOS镜像
- Hadoop源码分析--HDFS读取文件
- 如何升级CentOS 6.5下的MySQL
- tomcat+Gradle全自动打Android apk包方案
- docker中删除镜像的描述
- Apache server结合Tomcat配置集群与负载均衡
- ECSHOP去版权标志删除Powered by ECShop
- nginx反向代理hadoop集群管理页面
- hadoop伪分布式环境搭建记录
- linux ip 设置与获取
- 随机数——Linux C编程(ZZ)
- ArchLInux禁用触摸板