F:跳蛙【2019夏令营F】找不到提交入口正确性未知
-
总时间限制:
1000ms
-
内存限制:
65536kB
-
描述
在一个 1*n 的棋盘上生活着若干只青蛙:有恰好一只青蛙王和若干只(可能没有)普通青蛙。
我们用 A 表示青蛙王,B 表示普通青蛙,. 表示空地。
有一天,青蛙王醒来的时候发现它处在棋盘的最左侧,它想要跳到棋盘的最右侧。它可以指挥青蛙们来行动。
每一时刻可以选择下列操作中的一个进行操作:
- 对于青蛙王,如果它右侧相邻的格子是普通青蛙,且它右侧有空地的话,它可以跳到右侧第一个空地。
- 对于青蛙王,如果它左侧相邻的格子是普通青蛙,且它的左侧有空地的话,它可以跳到左侧第一个空地。
- 对于普通青蛙,如果它右侧相邻的格子是空地,它可以移动到这个空地。
- 对于普通青蛙,如果它左侧相邻的格子是空地,它可以移动到这个空地。
在移动的过程中,任意两只青蛙都不能同时移动,且任意一只青蛙不能移动出棋盘。现在给出初始时每一只青蛙的位置,问青蛙王能否到达棋盘的最右侧。
-
输入
输入包含多组数据。 每组数据第一行是一个整数 n(2<=n <= 10) 表示棋盘的大小。 第二行是一个长度为 n 的字符串从左到右表示棋盘的状态。保证第一个字符是 A,字符串只可能包含 AB. 三种字符,且恰好包含一个 A。 输入以 n=0 结束。
-
输出
对于每组数据,如果青蛙王能到达最右边,则输出 Y,否则输出 N。
-
样例输入
6 A.B..B 6 A.B... 6 ABBBBB 2 A. 0
-
样例输出
Y N N N
题解1
-
深搜,(青蛙王左边的普通青蛙数目lf,右边的普通青蛙数目rf,青蛙王当前位置start),其中**(lf, start)标识了一个状态**(lf和start都相同的出发状态的接下来的搜索过程是一样的)
- 如果左边有空位,则可以指挥[1,lf]i只青蛙移动到A的左边,然后A可以跳跃到这i只连续青蛙的左边;右边同理
- n<=10则lf和start<=10,因此lf*100+start可以唯一标识所以状态,且范围<1100
-
解释样例1
AB-B-- //指挥成这样 -BAB-- -B-BA- --BBA- //指挥成这样 -ABB-- -AB-B- //指挥成这样 --B-BA
#define MAX_STATE 1100
int visited[MAX_STATE]={0};
//idx from 1
int n;
bool solve(int lf, int rf, int start)
{
if(start==n){
return 1;
}
if(visited[lf*100+start]){
return 0;
}
visited[lf*100+start]=1;
//left
if(start-lf>1){
for(int i=1; i<=lf; ++i){
if(solve(lf-i, rf+i, start-i-1)){
return 1;
}
}
}
//right
if(start+rf<n){
for(int i=1; i<=rf; ++i){
if(solve(lf+i, rf-i, start+i+1)){
return 1;
}
}
}
//no solution
return 0;
}
int main()
{
while(cin>>n && n){
int lf=0,rf=0;
char c;
for(int i=0; i<n; ++i){
cin>>c;
if(c=='B'){
++rf;
}
}
if(solve(lf,rf,1)){
cout<<"Y"<<endl;
}
else{
cout<<"N"<<endl;
}
}
return 0;
}
题解2
-
看到大神的解答:只要有空位且普通青蛙数目>=2就一定有解
-
没有证明,不懂
-