原题链接:
题目大意:
7*8棋盘
不超过12个小球
以一个球击另一个球的方式将球击出棋盘,胜利的条件:最后只剩一个球。
1.两个球紧挨着推不动。
2.球会停在碰到下一个球时的位置。(例如:从左边击中球(3,4),则原球会停在(3,3))
3.不考虑动能损耗。
4.如果有多种情况就按照越左上角越好和U,L,R,D的优先级输出优先级最高的情况。(copy的,表示看不懂)
思路:
从第一个小球开始按“ULRD”的顺序搜索,DFS往下搜索第一种可能的情况。
代码如下:
#include<iostream>
#include<cstdio>
#include<cstring>
#include<string>
using namespace std;
const int MAXN=15;
char G[MAXN][MAXN];
const int next[][2]={{-1,0},{0,-1},{0,1},{1,0}};
const char * dir="ULRD";
int ans[MAXN];//记录小球被推下去的顺序
char ansdir[MAXN];//记录小球被推下去时的方向
int sum;//记录有多少个小球
bool check(int x,int y)
{
if(x>=0&&x<7&&y>=0&&y<8)
return true;
return false;
}
bool DFS(int num)
{
if(num==sum-1)
return true;
for(int i=0;i<7;i++)
{
for(int j=0;j<8;j++)
{
if(G[i][j]=='O')
{
for(int k=0;k<4;k++)
{
bool ishave=false;
int fx[MAXN];
int fy[MAXN];
int fs=0;
int tx=i+::next[k][0];
int ty=j+::next[k][1];
if(check(tx,ty)&&G[tx][ty]=='O')continue;//相邻的两个小球推不动
while(check(tx,ty))//记录下该方向上所有的小球
{
if(G[tx][ty]=='O')
{
ishave=true;
fx[fs]=tx;
fy[fs]=ty;
fs++;
}
tx+=::next[k][0];
ty+=::next[k][1];
}
if(ishave)//判断该方向上是否有小球
{
G[i][j]='X';
for(int h=0;h<fs;h++)//移动该方向上小球的位置
{
G[fx[h]][fy[h]]='X';
G[fx[h]-::next[k][0]][fy[h]-::next[k][1]]='O';
}
ans[num]=i*8+j;
ansdir[num]=dir[k];
if(DFS(num+1))//有正确答案就返回
return true;
G[i][j]='O';
tx=i+::next[k][0];
ty=j+::next[k][1];
while(check(tx,ty))//该方向上的小球全部清除
{
if(G[tx][ty]=='O')
{
G[tx][ty]='X';
}
tx+=::next[k][0];
ty+=::next[k][1];
}
for(int h=0;h<fs;h++)//恢复小球原来的位置
{
// G[fx[h]-::next[k][0]][fy[h]-::next[k][1]]='X';
G[fx[h]][fy[h]]='O';
}
}
}
}
}
}
return false;
}
int main()
{
int kase=0;
while(scanf("%s",G[0])!=EOF)
{
sum=0;
for(int i=1;i<7;i++)
scanf("%s",G[i]);
for(int i=0;i<7;i++)
for(int j=0;j<8;j++)
if(G[i][j]=='O')
sum++;
DFS(0);
if(kase++)
printf("\n");
printf("CASE #%d:\n",kase);
for(int i=0;i<sum-1;i++)
{
printf("%d %d %c\n",ans[i]/8,ans[i]%8,ansdir[i]);
}
}
return 0;
}