题目:
Description
CC公主被抓走了,为了救回她,你要通过九个关卡的考验。
在这一关中,你要通过一座浮桥。浮桥由多块漂浮的木板组成。不幸的是,水里生存着一种凶残的锦鱼,锦鱼的突刺会刺穿木板,如果你走到被刺穿的木板上,那么你就会掉进水里,然而你并不会游泳。幸好你学会了跳跃技能,可以跳过多块木板。
请问你最少要跳多少次,才能在不掉进水里的情况下到达对岸?
Input
输入的第一行包含一个正整数T(1<=T<=100)。T表示数据组数。
每一组数据的第一行包括两个整数L(1<=N<=1000)和M(1<=M<=1000)。L表示木板的个数。M表示一次跳跃你可以跳过的木板的个数。接下来一行包括一个长度为L的字符串,从左边数起,字符串的第i位为“O”表示第i个木板是完好的,为“X”表示第i个木板是被刺穿的。
一开始你站在第1个木板上,你的终点是第N个木板。
数据保证第1个木板和第N个木板是完好的。
Output
对于每组数据,如果可以抵达终点,在单独的一行中输出一个整数表示到达终点所需的最少跳跃次数。如果无法抵达终点,在单独的一行中输出“-1”。
Sample Input
4
3 1
OXO
3 2
OXO
9 3
OOOXOXOOO
6 2
OXOOXO
Sample Output
1
-1
1
2
HINT
对于第一个样例,你可以从第1个木板跳到第3个木板。
对于第二个样例,你无法抵达终点。
对于第三个样例,你可以走到第3个木板,然后跳到第7个木板,最后走到第9个木板。
对于第四个样例,你可以跳到第4个木板,然后走到第3个木板,最后跳到第6个木板。
我的想法与思路: 我通过对于字符串的处理来分割所有的可走路段和不可走路段,然后从第一个可走的路段向最后一个可走的路段搜索并用MIN记录最小值,可跳到第N个路段的判断方式是判断DUMP值处于两个路段中间的所有格子数 和 两个路段直接的所有格子数加两个路段自身的长度,处于这个区间便可以跳跃。
因为1<=N<=1000,所以最多拥有500个可走路段,纯搜索会存在很多不必要的判断,应为有可能DUMP已经远远小于我们记录的路段长度,但dfs依然在遍历后面的路段是否可以跳,所以我们可以进行优化,if ( num > dump ),则跳出搜索。
#include<iostream> #include<string.h> #include<string> using namespace std; int roads[1005]; int za[1005]; int road_num = 0; int za_num = 0; int len,dump; int MIN = __INT32_MAX__;//记录最小值 void dfs( int now , int end , int dump_num ){ if ( now == end && dump_num < MIN)//找到末尾并记录 MIN = dump_num; int num = 0; for ( int k = now + 1 ; k <= end ; k++ ){ if ( num > dump ) return; num += roads[ k ]; num += za[ k-1 ]; if ( num + roads[now] >= dump && dump >= num - roads[k] )//如果可以跳到第K个路段,就跳跃并继续搜索 dfs( k , end , dump_num + 1 ); } return; } int main(){ int n;cin>>n; while( n-- ){ cin>>len>>dump; MIN = __INT32_MAX__; memset( za , 0 , sizeof za ); memset( roads , 0 , sizeof roads ); road_num = 0; za_num = 0; string road; cin>>road; char Now = road[0]; while( road.length() != 0){ for ( int k = 0 ; k < road.length() ; k++ ){ if ( k == road.length() - 1 && road[k] == Now ){ Now=='O'?roads[road_num++] = k + 1:za[za_num++] = k + 1; road = ""; break; } if ( road[k] != Now ){ if ( Now == 'O' ){ roads[road_num++] = k;Now ='X'; }else{ za[za_num++] = k;Now='O'; } road = road.substr( k ); break; } } }//分割所有的障碍物和可走的路段 dfs( 0 , road_num - 1 , 0);//从路段0向最后一段路进行搜索 if ( MIN == __INT32_MAX__ ) MIN = -1; cout<<MIN<<endl; } return 0; }