1. (简答题)
实战题:打地鼠
内容如附件所示:
测试数据为:1,2,4,8,9,10,11,14 答案为:10,2,4
原始分布:
击打10号
击打2号
击打4号
要求,所示实例解以图示的方式给出,并且5组测试数据都需要测试,还要有无解数据测试,及游戏方式(给出初始状态,由用户输入敲几号,给出变化状态)。代码要给详细注释并贴图上传,运行结果贴图上传,源文件做为附件上传。
方法一:用宽搜
#include<bits/stdc++.h>
using namespace std;
int g[5][5]; //初始状态
int dx[5]={0,-1,0,1,0},dy[5]={0,0,1,0,-1}; //自身和周围四个格子
struct node{
int map[5][5];
int step; //敲了几只地鼠
int row[15]; //存储每次敲的位置所在行数
int col[15]; //存储每次敲的位置所在列数
}st,ed,en;
void bfs(int x,int y) //第一次敲的坐标
{
queue<node> q; //创立一个结构体队列
st.step=1; //敲的次数变为1
st.row[st.step]=x; //存储敲的地鼠所在行数
st.col[st.step]=y; //存储敲的地鼠所在列数
for(int i=1;i<=4;i++)
for(int j=1;j<=4;j++)
st.map[i][j]=g[i][j]; //先将敲前的地图存储
for(int i=0;i<5;i++)
if(x+dx[i]<=4&&x+dx[i]>0&&y+dy[i]<=4&&y+dy[i]>0)
st.map[x+dx[i]][y+dy[i]]=1-g[x+dx[i]][y+dy[i]];//把敲的地鼠周围的状态进行改变
q.push(st); //把这个结构体存入队列中
while(!q.empty())
{
st=q.front(); //将第一个结构体从队列中取出
q.pop(); //取完后将队列中第一个元素删除
int flag=1; //用于判断图中的地鼠是否都在地下
for(int j=1;j<=4;j++)
{
for(int k=1;k<=4;k++)
if(st.map[j][k]) //有至少一个地鼠在地上
{
flag=0; //判断标志变为0
break; //结束循环
}
if(!flag)
break;
}
if(flag) //地鼠全在地下
{ //用en存储st的step与格子,比较出step最小的走法
if(en.step>st.step) //将当前敲的次数与之前所求的敲的次数相比较,若这次更小,则取代
{
for(int z=1;z<=st.step;z++) //存储每次敲的坐标
{
en.row[z]=st.row[z];
en.col[z]=st.col[z];
}
en.step=st.step;
}
return;
}
if(st.step>=11) //这个代码运算量太大,就限定不敲超过十只地鼠
return;
for(int j=1;j<=4;j++)
for(int k=1;k<=4;k++)
{
if(st.map[j][k]) //寻找露头的地鼠
{
ed.step=st.step+1; //敲地鼠次数加1
for(int l=1;l<=4;l++)
for(int m=1;m<=4;m++)
ed.map[l][m]=st.map[l][m]; //将敲前的图存储到新结构体中
for(int e=0;e<5;e++)
{
if(j+dx[e]<=4&&j+dx[e]>=1&&k+dy[e]<=4&&k+dy[e]>=1) //找图内的点
ed.map[j+dx[e]][k+dy[e]]=1-ed.map[j+dx[e]][k+dy[e]];//将所敲地鼠及其周围四格状态进行改变
}
for(int l=1;l<=st.step;l++) //存储之前每次敲的位置
{
ed.row[l]=st.row[l];
ed.col[l]=st.col[l];
}
ed.row[ed.step]=j;
ed.col[ed.step]=k; //存储这次敲的位置
q.push(ed);
}
}
}
}
int main()
{
en.step=20; //求10步以内的解,将初始步数设为大于10的数
cout<<"该敲地鼠游戏共有4x4个洞,每个洞各有一只地鼠,每个地鼠的序号如下图所示:"<<endl;
int k=1;
for(int i=4;i>=1;i--) //构建格子(初始地图)
for(int j=1;j<=4;j++)
{
g[i][j]=k;
k++;
}
for(int i=1;i<=4;i++)
{
for(int j=1;j<=4;j++)
printf("%3d",g[i][j]); //展示序号
cout<<endl;
}
cout<<"该敲地鼠的规则如下: "<<endl;
cout<<"在初始时有部分地鼠会将头露在洞口,玩家的任务是在十步内能将所有地鼠敲入洞中,否则游戏失败!"<<endl;
cout<<"每次敲地鼠时,周围四格内露头的地鼠也会被吓回洞内,而原本在中的地鼠则会好奇地探出头来。"<<endl;
cout<<"请输入在洞口中露头的地鼠的序号(输入0时代表输入完毕):";
for(int i=1;i<=4;i++)
for(int j=1;j<=4;j++)
g[i][j]=0; //初始化为每个地鼠都没露头
while(1)
{
int x;
cin>>x;
if(x==0)
break;
if(x%4==0) //例如16->4 15->3.xxx 所有要特判
g[5-x/4][4]=1; //将输入的序号所指示的地鼠变为露头状态
else
g[4-x/4][x%4]=1;
}
cout<<"数据载入成功,初始图如下(1代表地鼠露头,0代表地鼠没露头):"<<endl;
for(int i=1;i<=4;i++)//输出 有地鼠的地图
{
for(int j=1;j<=4;j++)
cout<<g[i][j]<<" ";
cout<<endl;
}
cout<<endl<<"正在计算玩家在十步内能否取得胜利!"<<endl;
for(int i=1;i<=4;i++) //bfs遍历 第一次锤地鼠的格子
{
for(int j=1;j<=4;j++)
{
if(g[i][j])
{
bfs(i,j);
}
}
}
if(en.step<=10) //步数小于等于10说明有至少一个解
{
cout<<"玩家在十步内可以取得胜利,敲的顺序为:";
for(int i=1;i<=en.step;i++)
cout<<4*(4-en.row[i])+en.col[i]<<" "; //将坐标转换为序号输出
}
else
cout<<"玩家在十步内无法取得胜利!"<<endl;
return 0;
}