您的位置:首页 > 运维架构

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代码

#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;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: