历届试题 青蛙跳杯子
时间限制: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; }