历届试题 青蛙跳杯子
时间限制:1.0s 内存限制:256.0MB
问题描述
X星球的流行宠物是青蛙,一般有两种颜色:白色和黑色。
X星球的居民喜欢把它们放在一排茶杯里,这样可以观察它们跳来跳去。
如下图,有一排杯子,左边的一个是空着的,右边的杯子,每个里边有一只青蛙。
*WWWBBB
其中,W字母表示白色青蛙,B表示黑色青蛙,*表示空杯子。
X星的青蛙很有些癖好,它们只做3个动作之一:
1. 跳到相邻的空杯子里。
2. 隔着1只其它的青蛙(随便什么颜色)跳到空杯子里。
3. 隔着2只其它的青蛙(随便什么颜色)跳到空杯子里。
对于上图的局面,只要1步,就可跳成下图局面:
WWW*BBB
本题的任务就是已知初始局面,询问至少需要几步,才能跳成另一个目标局面。
输入为2行,2个串,表示初始局面和目标局面。
输出要求为一个整数,表示至少需要多少步的青蛙跳。
X星球的居民喜欢把它们放在一排茶杯里,这样可以观察它们跳来跳去。
如下图,有一排杯子,左边的一个是空着的,右边的杯子,每个里边有一只青蛙。
*WWWBBB
其中,W字母表示白色青蛙,B表示黑色青蛙,*表示空杯子。
X星的青蛙很有些癖好,它们只做3个动作之一:
1. 跳到相邻的空杯子里。
2. 隔着1只其它的青蛙(随便什么颜色)跳到空杯子里。
3. 隔着2只其它的青蛙(随便什么颜色)跳到空杯子里。
对于上图的局面,只要1步,就可跳成下图局面:
WWW*BBB
本题的任务就是已知初始局面,询问至少需要几步,才能跳成另一个目标局面。
输入为2行,2个串,表示初始局面和目标局面。
输出要求为一个整数,表示至少需要多少步的青蛙跳。
样例输入
*WWBB
WWBB*
WWBB*
样例输出
2
样例输入
WWW*BBB
BBB*WWW
BBB*WWW
样例输出
10
数据规模和约定
我们约定,输入的串的长度不超过15
资源约定:
峰值内存消耗(含虚拟机) < 256M
CPU消耗 < 1000ms
请严格按要求输出,不要画蛇添足地打印类似:“请您输入...” 的多余内容。
所有代码放在同一个源文件中,调试通过后,拷贝提交该源码。
不要使用package语句。不要使用jdk1.7及以上版本的特性。
主类的名字必须是:Main,否则按无效代码处理。
----------------------------
笨笨有话说:
我梦见自己是一棵大树,
青蛙跳跃,
我就发出新的枝条,
春风拂动那第 5 层的新枝,
哦,我已是枝繁叶茂。
资源约定:
峰值内存消耗(含虚拟机) < 256M
CPU消耗 < 1000ms
请严格按要求输出,不要画蛇添足地打印类似:“请您输入...” 的多余内容。
所有代码放在同一个源文件中,调试通过后,拷贝提交该源码。
不要使用package语句。不要使用jdk1.7及以上版本的特性。
主类的名字必须是:Main,否则按无效代码处理。
----------------------------
笨笨有话说:
我梦见自己是一棵大树,
青蛙跳跃,
我就发出新的枝条,
春风拂动那第 5 层的新枝,
哦,我已是枝繁叶茂。
这题我用的是广搜,想了小半天,终于出来了,但是提交的时候还是有两个数据超时
下面是我的思路:
从当前空杯子处找所有可能的跳法,并将每种可能一一入队,例如有7个杯子,中间的是空杯子,则有6种可能跳法
其他情况以此类推。
每次用过的串用一个新的数组存起来,避免重复使用,浪费时间。每次用时比对一下看其是否用过,如果用过则不用。
当找到目标串就ok了。
下面上代码
#include<stdio.h>
#include<string.h>
char start[16];
char aim[16];
int length;
int map[100000]={0};
typedef struct node{
int step;
int id;
char mid[16];
}Queue;
Queue ss[100000];//新数组 存放已经使用过的串
int slen=0; //新数组长度
int ok(char mid[]) //判断是否找到目标串
{
int i;
for(i=0;i<length;i++)
{
if(mid[i]!=aim[i])
return 0;
}
return 1;
}
int reok(char arr[16]) //判断当前串是否已经用过
{
int i,j;
int x;
for(i=0;i<slen;i++)
{
x=0;
for(j=0;j<length;j++)
{
if(ss[i].mid[j]==arr[j])
{
x++;
}
}
if(x==length) //全部相同表明使用过
{
return 1;
}
}
return 0;
}
void bfs(char mid[16],int emptyid)
{
Queue q[10000];
int h=-1,p=0,len=0;
q[p].id=emptyid;
q[p].step=0;
strcpy(q[p].mid,mid);
p++,h++,len++;
while(len!=0)
{
int id=q[h].id,step=q[h].step;
int flagid=id;
strcpy(mid,q[h].mid);
h++,len--;
if(ok(mid))
{
printf("%d\n",step);
return ;
}
else
{
char mmid[16]; //每次从当前根节点出发去寻找可行性叶子 ---也就是找寻从当前串青蛙能跳的所有可能
int temp;
if(reok(mid)) //如果上次来过当前根节点则不继续从该节点搜
continue;
if(id-1>=0)
{
strcpy(mmid,mid);
q[p].id=id-1;
q[p].step=step+1;
temp=mmid[id];
mmid[id]=mmid[id-1];
mmid[id-1]=temp;
strcpy(q[p].mid,mmid);
p++,len++;
}
if(id+1<length)
{
strcpy(mmid,mid);
q[p].id=id+1;
q[p].step=step+1;
temp=mmid[id];
mmid[id]=mmid[id+1];
mmid[id+1]=temp;
strcpy(q[p].mid,mmid);
p++,len++;
}
if(id-2>=0)
{
strcpy(mmid,mid);
q[p].id=id-2;
q[p].step=step+1;
temp=mmid[id];
mmid[id]=mmid[id-2];
mmid[id-2]=temp;
strcpy(q[p].mid,mmid);
p++,len++;
}
if(id+2<length)
{
strcpy(mmid,mid);
q[p].id=id+2;
q[p].step=step+1;
temp=mmid[id];
mmid[id]=mmid[id+2];
mmid[id+2]=temp;
strcpy(q[p].mid,mmid);
p++,len++;
}
if(id-3>=0)
{
strcpy(mmid,mid);
q[p].id=id-3;
q[p].step=step+1;
temp=mmid[id];
mmid[id]=mmid[id-3];
mmid[id-3]=temp;
strcpy(q[p].mid,mmid);
p++,len++;
}
if(id+3<length)
{
strcpy(mmid,mid);
q[p].id=id+3;
q[p].step=step+1;
temp=mmid[id];
mmid[id]=mmid[id+3];
mmid[id+3]=temp;
strcpy(q[p].mid,mmid);
p++,len++;
}
}
strcpy(ss[slen++].mid,mid); //用过了就存入新数组
}
}
int main()
{
char mid[16];
int i,j;
int emptyid;
scanf("%s",start);
scanf("%s",aim);
length=strlen(start);
for(i=0;i<length;i++)
{
if(start[i]=='*')
emptyid=i;
}
for(i=0;i<length;i++)
{
mid[i]=start[i];
}
bfs(mid,emptyid);
return 0;
}