• [kuangbin带你飞]专题一 简单搜索 题解报告


    又重头开始刷kuangbin,有些题用了和以前不一样的思路解决。全部题解如下

    点击每道题的标题即可跳转至VJ题目页面。

    A-棋盘问题

    棋子不能摆在相同行和相同列,所以我们可以依此枚举每一行,然后标记每一列是否走过,在此基础上进行DFS即可。

    代码如下:

     1 #include <iostream>
     2 #include <cstring>
     3 using namespace std;
     4 int n,m,sum;
     5 char mp[10][10];
     6 int vis[10] = {0};
     7 
     8 void dfs(int r,int k){
     9   if(k == m){
    10     sum++;
    11     return ;  
    12   }
    13   for(int i = r; i < n; i++){
    14     for(int j = 0; j < n; j++){
    15       if(mp[i][j] == '#' && !vis[j]){
    16         vis[j] = 1;
    17         dfs(i+1,k+1);
    18         vis[j] = 0;
    19       }
    20     }
    21   }
    22 }
    23 
    24 int main(){
    25   while(cin>>n>>m && n > 0 && m > 0){
    26     memset(vis, 0, sizeof vis);
    27     sum = 0;
    28     for(int i = 0; i < n; i++){
    29       for(int j = 0; j < n; j++){
    30         cin>>mp[i][j];
    31       }
    32     }
    33     dfs(0,0);
    34     cout << sum << endl;
    35   }
    36   return 0;
    37 }

    B-Dungeon Master

    题意就是给你一个三维的迷宫,从S走到E,判断能否逃脱若能逃离则输出最短时间。

    裸BFS/DFS,只是多了两个方向,向上走和向下走,我用的是BFS,代码如下:

     1 #include <iostream>
     2 #include <cstring>
     3 #include <queue>
     4 using namespace std;
     5 
     6 int r,c,h;
     7 char mp[35][35][35];
     8 bool vis[35][35][35];
     9 int sz,sx,sy,ez,ex,ey;
    10 
    11 int fx[6][3] = {{1,0,0},{-1,0,0},{0,1,0},{0,-1,0},{0,0,-1},{0,0,1}};
    12 
    13 struct node{
    14     int z,x,y,t;
    15 };
    16 
    17 bool check(int x,int y,int z){
    18     if(mp[z][x][y] == '#' || vis[z][x][y] || z < 0 || z >= h || x < 0 || x >= r || y < 0 || y >= c){
    19         return false;
    20     }
    21     vis[z][x][y] = 1;
    22     return true;
    23 }
    24 
    25 int bfs(){
    26     memset(vis, false, sizeof vis);
    27     queue<node> q;
    28     q.push(node{sz,sx,sy,0});
    29     vis[sz][sx][sy] = 1;
    30     while(!q.empty()){
    31         node now = q.front();
    32         q.pop();
    33         //cout << now.z << " " << now.x << " " << now.y << endl;
    34         if(now.z == ez && now.x == ex && now.y == ey){
    35             return now.t;
    36         }
    37         for(int i = 0; i < 6; i++){
    38             int nx = now.x + fx[i][0];
    39             int ny = now.y + fx[i][1];
    40             int nz = now.z + fx[i][2];
    41             if(check(nx,ny,nz)){
    42                 q.push(node{nz,nx,ny,now.t+1});
    43             }
    44         }
    45     }
    46     return -1;
    47 }
    48 
    49 
    50 int main(){
    51     ios_base::sync_with_stdio(0);
    52     while(cin >> h >> r >> c && r ){
    53         for(int k = 0; k < h; k++){
    54             for(int i = 0; i < r; i++){
    55                 for(int j = 0; j < c; j++){
    56                     cin>>mp[k][i][j];
    57                     if(mp[k][i][j] == 'S'){
    58                         sz = k,sx = i,sy = j;
    59                     }
    60                     else if(mp[k][i][j] == 'E'){
    61                         ez = k,ex = i,ey = j;
    62                     }
    63                 }
    64             }
    65         }
    66         int ret = bfs();
    67         if(ret == -1)
    68             cout << "Trapped!" << endl;
    69         else
    70             cout << "Escaped in " << ret << " minute(s)." << endl;
    71 
    72     }
    73     return 0;
    74 }

    C-Catch That Cow

    题意就是你现在在n位置处,牛在k位置处,你有下面三种走路方式,每次花费一分钟,牛不会动,问抓到牛的最小时间。

    • 走到x+1位置处
    • 走到x-1位置处
    • 走到x*2位置处

    BFS模拟即可,注意判断走到x*2时候,应该先判断x*2是否越界再判断vis[x*2]是否走过,可以用短路运算符&&实现,否则会造成RE,当然你也可以开成两倍的 数组空间来避免这种错误,但我还是推荐使用前者方式。

    代码如下:

     1 #include <iostream>
     2 #include <cstring>
     3 #include <queue>
     4 using namespace std;
     5 
     6 int n,k;
     7 bool vis[100005];
     8 
     9 struct node{
    10     int s,t;
    11 };
    12 
    13 int bfs(){
    14     memset(vis,0,sizeof vis);
    15     queue<node> q;
    16     q.push(node{n,0});
    17     vis[n] = 1;
    18     while(!q.empty()){
    19         node now = q.front();
    20         q.pop();
    21         if(now.s == k)
    22             return now.t;
    23         if(now.s-1 >= 0 && !vis[now.s-1]){
    24             vis[now.s-1] = 1;
    25             q.push(node{now.s-1,now.t+1});
    26         }
    27         if(now.s+1 <= 100000 && !vis[now.s+1]){
    28             vis[now.s+1] = 1;
    29             q.push(node{now.s+1,now.t+1});
    30         }
    31         if(now.s*2 <= 100000 && !vis[now.s*2]){
    32             vis[now.s*2] = 1;
    33             q.push(node{now.s*2,now.t+1});
    34         }
    35     }
    36     return 0;
    37 }
    38 
    39 int main(){
    40     ios_base::sync_with_stdio(0);
    41     while(cin>>n>>k){
    42         cout << bfs() << endl;
    43     }
    44     return 0;
    45 }

    D-Fliptile

     玩过关灯游戏理解这个题就很简单,n*m的矩阵,0代表灯关,1代表灯开,然后可以反转某个灯的状态,但是这个灯周围四个方向的灯也会反转,然后问如何吧所有灯全关掉,若是不可能则输出IMPOSSIBLE,若是有多种情况请输出字典序最小的那个操作矩阵。

    思路就是枚举,如何枚举,首先我们可以枚举第一层的每种操作可能,若是上一层有灯没关,这层的相应位置则必须反转,这样只要判断最下面一层的灯是否全关了即可。

    那么我们需要对第一层枚举多少种状态呢?答案是2^m种,为什么呢,因为每层有m个灯,每种灯两个状态,所以就是2^m种操作方式,每种操作方式也就刚好对应了0——2^m-1中数的二进制,

    例如对于样例,需要枚举0——15

    0 = 0000

    1 = 0001

    ……

    15 = 1111

    二进制刚好就是第一层的操作方式,然后我们从第二层开始,判断上一层是否还有状态为灯开的灯,有则操作当前位置,再判断最后一层是否全为灯关。

    至于字典序处理,我们只需要数操作矩阵1的个数,找最小值即可,你可能会问相等的情况呢,因为我们是按0->2^m-1,所以若是前面的1个数和后面1个数相等,字典序一定是前面的更小,所以无需考虑。

    代码如下:

     1 #include <iostream>
     2 #include <cstring>
     3 #include <queue>
     4 #include <vector>
     5 #include <string>
     6 #include <iomanip>
     7 #include <cmath>
     8 #include <climits>
     9 using namespace std;
    10 
    11 int n,m;
    12 int mp[20][20],fp[20][20],vis[20][20];
    13 int fx[4][2] = {{1,0},{-1,0},{0,1},{0,-1}};
    14 
    15 void change(int i,int j){
    16     fp[i][j] ^= 1;
    17     for(int k = 0; k < 4; k++){
    18         int ni = i + fx[k][0];
    19         int nj = j + fx[k][1];
    20         if(ni >= 0 && nj >= 0 && ni < n && nj < m){
    21             fp[ni][nj] ^= 1;
    22         }
    23     }
    24 }
    25 
    26 int dfs(int k){
    27     memcpy(fp, mp, sizeof fp);
    28     memset(vis, 0, sizeof vis);
    29     int tot = m-1,res = 0;
    30     while(k || tot>=0){
    31         int t = k%2;
    32         vis[0][tot] = t;
    33         res+=t;
    34         if(t == 1)
    35             change(0,tot);
    36         tot--;
    37         k /= 2;
    38     }
    39     //cout  << setw(3) << setfill('0') << *fp[0] << endl;
    40     for(int i = 1; i < n; i++){
    41         for(int j = 0; j < m; j++){
    42             if(fp[i-1][j] == 1){
    43                 vis[i][j] = 1;
    44                 res++;
    45                 change(i,j);
    46             }
    47         }
    48     }
    49     for(int j = 0; j < m; j++){
    50         if(fp[n-1][j] == 1)
    51             return 15*15*2;
    52     }
    53     return res;
    54 }
    55 
    56 int main(){
    57     ios_base::sync_with_stdio(0),cin.tie(0),cout.tie(0);
    58     while(cin>>n>>m){
    59         int ans[20][20];
    60         for(int i = 0; i < n; i++){
    61             for(int j = 0; j < m; j++){
    62                 cin>>mp[i][j];
    63             }
    64         }
    65         int num = pow(2,m),minn = INT_MAX;
    66         for(int i = 0; i < num; i++){
    67             int ret = dfs(i);
    68             if(ret < minn){
    69                 memcpy(ans, vis, sizeof vis);
    70                 minn = ret;
    71             }
    72         }
    73         if(minn == 15*15*2)
    74             cout << "IMPOSSIBLE" << endl;
    75         else{
    76             for(int i = 0; i < n; i++){
    77                 for(int j = 0; j < m; j++){
    78                     if(j == 0)
    79                         cout << ans[i][j];
    80                     else
    81                         cout << " " << ans[i][j];
    82                 }
    83                 cout << endl;
    84             }
    85         }
    86     }
    87     return 0;
    88 }

    E-Find The Multiple

    题意就是给你一个数n,然后让你找到一个只由1和0构成的数x,使得x是n的倍数。

    BFS遍历即可,所有数组都在long long范围内有解,其实甚至都不需要BFS,直接依此枚举即可。

    代码如下:

     1 #include <iostream>
     2 #include <cstring>
     3 #include <queue>
     4 #include <string>
     5 using namespace std;
     6 
     7 int n;
     8 
     9 long long bfs(){
    10     queue<long long> q;
    11     q.push(1);
    12     while(!q.empty()){
    13         long long x = q.front();
    14         q.pop();
    15         if(x % n == 0){
    16             return x;
    17         }
    18         q.push(x*10);
    19         q.push(x*10+1);
    20     }
    21     return 0;
    22 }
    23 
    24 int main(){
    25     while(cin>>n && n){
    26         cout << bfs() << endl;
    27     }
    28     return 0;
    29 }

    F-Prime Path

    题意就是给你两个数p1,p2,两个数都是四位数且都是素数,现在要把p1变成p2,规则是每次只能变换某一位上的数,且保证变换过程中的数也是素数。求最小变换次数。

    还是BFS撒,从最高位开始变换,枚举所有素数的变换情况直至找到p2位置,这题麻烦的是变一位的数。

    代码如下:

     1 #include <iostream>
     2 #include <queue>
     3 #include <algorithm>
     4 #include <string>
     5 #include <cstring>
     6 #include <cmath>
     7 using namespace std;
     8 
     9 int a,b;
    10 int sum = 0;
    11 bool vis[10005];
    12 
    13 struct node{
    14     int x,s;
    15 };
    16 
    17 int change(int k,int i,int j){
    18     return k - (int(k/pow(10,3-i))%10)*pow(10,3-i) + j*pow(10,3-i);
    19 }
    20 
    21 bool isprime(int n){
    22     if(n==2 || n==3)
    23         return true;
    24     if(n%6 != 1 && n%6 != 5)
    25         return false;
    26     float n_sqrt = floor(sqrt((float)n));
    27     for(int i = 5; i <= n_sqrt; i += 6)
    28         if(n%(i) == 0 | n%(i+2) == 0)
    29             return false;
    30     return true;
    31 }
    32 
    33 int bfs(int k){
    34     vis[k] = 1;
    35     queue<node> q;
    36     q.push(node{k,0});
    37     while(!q.empty()){
    38         node now = q.front();
    39         //cout << now.x << endl;
    40         q.pop();
    41         if(now.x == b)
    42             return now.s;
    43         for(int i = 0; i < 4; i++){
    44             for(int j = 9; j >= 0; j--){
    45                 if(i == 0 && j == 0) break;
    46                 int t = change(now.x,i,j);
    47                 if(isprime(t) && !vis[t]){
    48                     vis[t] = 1;
    49                     q.push(node{t,now.s+1});
    50                 }
    51             }
    52         }
    53     }
    54     return 0;
    55 }
    56 
    57 int main(){
    58     int t;
    59     cin>>t;
    60     while(t--){
    61         memset(vis, 0, sizeof vis);
    62         cin>>a>>b;
    63         sum = bfs(a);
    64         cout << sum << endl;
    65     }
    66     return 0;
    67 }

    G-Shuffle'm Up

    给你两个字符串长度都为n的字符串s1、s2,然后可以结合成题目图中那种形状,s2和s1交叉且s2的最下面一块在结合后的形状中还是最下面一块,s1又变成结合后的串的前n个字符,s2变成后n个字符,判断能否得到想要的字符串并询问最小变换次数。

    主要考字符串处理,代码如下:

     1 #include <iostream>
     2 #include <cstring>
     3 #include <cmath>
     4 #include <algorithm>
     5 #include <map>
     6 using namespace std;
     7 
     8 string s1,s2,es;
     9 int n;
    10 map<string,int> vis;
    11 
    12 string fun(string a,string b){
    13     string s = "";
    14     for(int i = 0; i < n; i++){
    15         s += b[i];
    16         s += a[i];
    17     }
    18     return s;
    19 }
    20 
    21 int bfs(){
    22     int tot = 0;
    23     while(1){
    24         tot ++;
    25         string ss = fun(s1,s2);
    26         //cout << ss << endl;
    27         if(ss == es)
    28             return tot;
    29         if(!vis[ss])
    30             vis[ss] = 1;
    31         else
    32             break;
    33         s1 = ss.substr(0,n);
    34         s2 = ss.substr(n,n);
    35     }
    36     return -1;
    37 }
    38 
    39 int main(){
    40     int t;
    41     cin>>t;
    42     for(int tt = 1; tt <= t; tt++){
    43         cin>>n>>s1>>s2>>es;
    44         cout  << tt << ' ' << bfs() << endl;
    45     }
    46     return 0;
    47 }

    H-Pots

    题意:有两个壶,容量分别为A,B,现在想要C(C ≤ max(a,b))容量的水,然后可以相互倒水(只能倒到另一壶满或者本壶倒完为止),倒空本壶,装满本壶。问操作次数(SPJ,不需要最小操作 次数)并且应该如何操作。

    因为有SPJ存在,所以直接BFS就行了,主要麻烦的是如何存储每次的操作。我是用一个vector<pair<char,int>>来实现,这样会消耗很大的空间,但题目空间很充裕,所以这个做法没有问题。

    代码如下:

      1 #include <iostream>
      2 #include <cstring>
      3 #include <cmath>
      4 #include <algorithm>
      5 #include <map>
      6 #include <vector>
      7 #include <queue>
      8 using namespace std;
      9 
     10 int a,b,c;
     11 bool vis[105][105];
     12 
     13 struct node{
     14     int a,b;
     15     vector< pair<char,int> > v;
     16 };
     17 
     18 void print(node n){
     19     cout << n.v.size() << endl;
     20     for(vector< pair<char,int> >::iterator it = n.v.begin(); it != n.v.end(); it++){
     21         if(it->first == 'f')
     22             cout << "FILL(" << it->second << ")" << endl;
     23         else if(it->first == 'd')
     24             cout << "DROP(" << it->second << ")" << endl;
     25         else if(it->first == 'p')
     26             cout << "POUR(" << it->second << ',' << (it->second == 1?2:1) << ")" << endl;
     27     }
     28     return ;
     29 }
     30 
     31 void bfs(){
     32     memset(vis, 0, sizeof vis);
     33     queue<node> q;
     34     q.push(node{0,0});
     35     vis[a][b] = 1;
     36     while(!q.empty()){
     37         node now = q.front(),nt;
     38         //cout << now.a << ' ' << now.b << endl;
     39         q.pop();
     40         if(now.a == c || now.b == c){
     41             print(now);
     42             return ;
     43         }
     44         if(now.a != 0 && !vis[0][now.b]){
     45             vis[0][now.b] = 1;
     46             nt = now;
     47             nt.a = 0;
     48             nt.v.push_back(make_pair('d',1));
     49             q.push(nt);
     50         }
     51         if(now.b != 0 && !vis[0][now.a]){
     52             vis[now.a][0] = 1;
     53             nt = now;
     54             nt.b = 0;
     55             nt.v.push_back(make_pair('d',2));
     56             q.push(nt);
     57         }
     58         if(now.a != a && !vis[a][now.b]){
     59             vis[a][now.b] = 1;
     60             nt = now;
     61             nt.a = a;
     62             nt.v.push_back(make_pair('f',1));
     63             q.push(nt);
     64         }
     65         if(now.b != b && !vis[b][now.a]){
     66             vis[now.a][b] = 1;
     67             nt = now;
     68             nt.b = b;
     69             nt.v.push_back(make_pair('f',2));
     70             q.push(nt);
     71         }
     72         if(now.a > 0 && now.b != b){
     73             int tb = now.b+now.a >= b?b:now.b+now.a;
     74             int ta = b-now.b >= now.a?0:now.a-b+now.b;
     75             if(!vis[ta][tb]){
     76                 vis[ta][tb] = 1;
     77                 nt = now;
     78                 nt.a = ta;
     79                 nt.b = tb;
     80                 nt.v.push_back(make_pair('p',1));
     81                 q.push(nt);
     82             }
     83         }
     84         if(now.a != a && now.b > 0){
     85             int ta = now.a+now.b >= a?a:now.a+now.b;
     86             int tb = a-now.a >= now.b?0:now.b-a+now.a;
     87             if(!vis[ta][tb]){
     88                 vis[ta][tb] = 1;
     89                 nt = now;
     90                 nt.a = ta;
     91                 nt.b = tb;
     92                 nt.v.push_back(make_pair('p',2));
     93                 q.push(nt);
     94             }
     95         }
     96     }
     97     cout << "impossible" << endl;
     98     return ;
     99 }
    100 
    101 int main(){
    102     while(cin>>a>>b>>c){
    103         bfs();
    104     }
    105     return 0;
    106 }

    I-Fire!

    题意就是人在J位置处,火在F位置处,不一定只有一堆火,火每分钟会向四周蔓延,人每分钟可以走一格,问能否逃出以及最小逃跑时间。

    做了一遍再对比了一下以前的代码,发现区别还是很大的,以前是人每走一格就去BFS使得火蔓延一次,现在的做法是BFS人到达每个出口的时间,再BFS火到达每个出口的时间,再判断大小也就是判断人能否在火之前到达出口。

    两份代码如下:

    BEFORE(乱七八糟的宏定义比较多= =):

      1 #include <iostream>
      2 #include <string>
      3 #include <cstdio>
      4 #include <cstdlib>
      5 #include <sstream>
      6 #include <iomanip>
      7 #include <map>
      8 #include <stack>
      9 #include <deque>
     10 #include <queue>
     11 #include <vector>
     12 #include <set>
     13 #include <list>
     14 #include <cstring>
     15 #include <cctype>
     16 #include <algorithm>
     17 #include <iterator>
     18 #include <cmath>
     19 #include <bitset>
     20 #include <ctime>
     21 #include <fstream>
     22 #include <limits.h>
     23 #include <numeric>
     24 
     25 using namespace std;
     26 
     27 #define F first
     28 #define S second
     29 #define mian main
     30 #define ture true
     31 
     32 #define MAXN 1000000+5
     33 #define MOD 1000000007
     34 #define PI (acos(-1.0))
     35 #define EPS 1e-6
     36 #define MMT(s) memset(s, 0, sizeof s)
     37 typedef unsigned long long ull;
     38 typedef long long ll;
     39 typedef double db;
     40 typedef long double ldb;
     41 typedef stringstream sstm;
     42 const int INF = 0x3f3f3f3f;
     43 
     44 int n,m,t,jx,jy;
     45 char mp[1005][1005];
     46 int vis[1005][1005];
     47 int fx[4][2] = {1,0,-1,0,0,-1,0,1};
     48 vector< pair<int,int> >q;
     49 
     50 void init(){
     51     MMT(mp);
     52     fill(vis[0],vis[0]+1005*1005,0);
     53     q.clear();
     54 }
     55 
     56 bool check(int x,int y){
     57     if(x < 0 || x >= n || y < 0 || y >= m || mp[x][y] == '#' || vis[x][y])
     58         return false;
     59     return true;
     60 }
     61 
     62 int bfs(){
     63     queue< pair<int,int> >p;
     64     queue< pair<int,int> >pf;
     65     p.push(make_pair(jx,jy));
     66     int step = 0;
     67     for(int i = 0, len = q.size(); i < len; i++){
     68         vis[q[i].F][q[i].S] = 1;
     69         pf.push(q[i]);
     70     }
     71     vis[jx][jy] = 1;
     72     while(!p.empty()){
     73         pair<int,int>nx = p.front();
     74 
     75         if(nx.F == 0 || nx.F == n-1 || nx.S == 0 || nx.S == m-1)
     76             return vis[nx.F][nx.S];
     77 
     78         if(vis[nx.F][nx.S] > step)
     79             step++;
     80         if(vis[nx.F][nx.S] == step){
     81             while(!pf.empty()){
     82                 pair<int,int>nf = pf.front();
     83                 if(vis[nf.F][nf.S] > step)
     84                     break;
     85                 pf.pop();
     86                 for(int i = 0; i < 4; i++){
     87                     int nxx = nf.F + fx[i][0];
     88                     int nxy = nf.S + fx[i][1];
     89                     if(check(nxx,nxy)){
     90                         vis[nxx][nxy] = vis[nf.F][nf.S] + 1;
     91                         pf.push(make_pair(nxx,nxy));
     92                     }
     93                 }
     94             }
     95         }
     96         p.pop();
     97         for(int i = 0; i < 4; i++){
     98             int nxx = nx.F + fx[i][0];
     99             int nxy = nx.S + fx[i][1];
    100             if(check(nxx,nxy)){
    101                 vis[nxx][nxy] = vis[nx.F][nx.S] + 1;
    102                 p.push(make_pair(nxx,nxy));
    103             }
    104         }
    105     }
    106     return -1;
    107 }
    108 
    109 int main(){
    110     ios_base::sync_with_stdio(false);
    111     cout.tie(0);
    112     cin.tie(0);
    113     cin>>t;
    114     while(t--){
    115         init();
    116         cin>>n>>m;
    117         for(int i = 0; i < n; i++){
    118             for(int j = 0; j < m; j++){
    119                 cin>>mp[i][j];
    120                 if(mp[i][j] == 'J'){
    121                     jx = i, jy = j;
    122                 }
    123                 if(mp[i][j] == 'F'){
    124                     q.push_back(make_pair(i,j));
    125                 }
    126             }
    127         }
    128         int ret = bfs();
    129         if(ret > 0)
    130             cout << ret << endl;
    131         else
    132             cout << "IMPOSSIBLE" << endl;
    133 
    134     }
    135     return 0;
    136 }

    NOW:

      1 #include <iostream>
      2 #include <cstring>
      3 #include <cmath>
      4 #include <algorithm>
      5 #include <map>
      6 #include <vector>
      7 #include <climits>
      8 #include <queue>
      9 using namespace std;
     10 
     11 int n,m;
     12 char mp[1005][1005];
     13 int dis[1005][1005];
     14 int fdis[1005][1005];
     15 bool vis[1005][1005];
     16 int px,py;
     17 int fx[4][2] = {{1,0},{-1,0},{0,-1},{0,1}};
     18 struct node{
     19     int x,y;
     20 };
     21 
     22 queue<node> q[2];
     23 
     24 bool pass1(int x,int y){
     25     if(x < 0 || y < 0 || x >= n || y >= m || mp[x][y] != '.' || dis[x][y])
     26         return false;
     27     return true;
     28 }
     29 
     30 bool pass2(int x,int y){
     31     if(x < 0 || y < 0 || x >= n || y >= m || mp[x][y] == '#' || fdis[x][y])
     32         return false;
     33     return true;
     34 }
     35 
     36 void bfs(){
     37     while(!q[0].empty()){
     38         node now = q[0].front();
     39         q[0].pop();
     40         for(int i = 0; i < 4; i++){
     41             int nx = now.x + fx[i][0];
     42             int ny = now.y + fx[i][1];
     43             if(pass1(nx,ny)){
     44                 q[0].push(node{nx,ny});
     45                 dis[nx][ny] = dis[now.x][now.y]+1;
     46             }
     47         }
     48     }
     49 
     50     while(!q[1].empty()){
     51         node now = q[1].front();
     52         q[1].pop();
     53         for(int i = 0; i < 4; i++){
     54             int nx = now.x + fx[i][0];
     55             int ny = now.y + fx[i][1];
     56             if(pass2(nx,ny)){
     57                 q[1].push(node{nx,ny});
     58                 fdis[nx][ny] = fdis[now.x][now.y]+1;
     59             }
     60         }
     61     }
     62 }
     63 
     64 int check(){
     65     int ans = INT_MAX;
     66     for(int j = 0; j < m; j++){
     67         if(dis[0][j] > 0 && (fdis[0][j] > dis[0][j] || fdis[0][j] == 0))
     68             ans = min(ans,dis[0][j]);
     69         if(dis[n-1][j] > 0 && (fdis[n-1][j] > dis[n-1][j] || fdis[n-1][j] == 0))
     70             ans = min(ans,dis[n-1][j]);
     71     }
     72     for(int j = 0; j < n; j++){
     73         if(dis[j][0] > 0 && (fdis[j][0] > dis[j][0] || fdis[j][0] == 0))
     74             ans = min(ans,dis[j][0]);
     75         if(dis[j][m-1] > 0 && (fdis[j][m-1] > dis[j][m-1] || fdis[j][m-1] == 0))
     76             ans = min(ans,dis[j][m-1]);
     77     }
     78     if(ans == INT_MAX)
     79         return -1;
     80     else
     81         return ans;
     82 }
     83 
     84 void init(){
     85     while(!q[0].empty()) q[0].pop();
     86     while(!q[1].empty()) q[1].pop();
     87     memset(dis, 0, sizeof dis);
     88     memset(fdis, 0, sizeof fdis);
     89     return ;
     90 }
     91 
     92 int main(){
     93     int t;
     94     cin>>t;
     95     while(t--){
     96         init();
     97         cin>>n>>m;
     98         for(int i = 0; i < n; i++){
     99             for(int j = 0; j < m; j++){
    100                 cin>>mp[i][j];
    101                 if(mp[i][j] == 'J')
    102                     q[0].push(node{i,j}),dis[i][j] = 1;
    103                 if(mp[i][j] == 'F')
    104                     q[1].push(node{i,j}),fdis[i][j] = 1;
    105             }
    106         }
    107         bfs();
    108         int ret = check();
    109         if(ret == -1)
    110             cout << "IMPOSSIBLE" << endl;
    111         else
    112             cout << ret << endl;
    113     }
    114     return 0;
    115 }

    J-迷宫问题

    这个我以前写过一篇博客https://www.cnblogs.com/xenny/p/9473555.html

    然后再贴一下现在的代码吧:

     1 #include <iostream>
     2 #include <algorithm>
     3 #include <cstring>
     4 #include <queue>
     5 #include <stack>
     6 #include <vector>
     7 using namespace std;
     8 
     9 char mp[5][5];
    10 bool vis[5][5];
    11 int fx[4][2] = {{1,0},{-1,0},{0,1},{0,-1}};
    12 vector< pair<int,int> > ans(1,make_pair(0,0));
    13 bool pass(int x,int y){
    14     if(x < 0 || y < 0 || x >= 5 || y >= 5 || vis[x][y] || mp[x][y] == '1')
    15         return false;
    16     return true;
    17 }
    18 
    19 void print(vector< pair<int,int> > v){
    20     for(vector< pair<int,int> >::iterator it = v.begin(); it != v.end(); it++){
    21         cout << '(' << it->first << ", " << it->second << ')' << endl;
    22     }
    23 }
    24 
    25 void dfs(int x,int y,vector< pair<int,int> > v){
    26     if(x == 4 && y == 4){
    27         if(ans.size() == 1 || v.size() < ans.size())
    28             ans = v;
    29         return ;
    30     }
    31     for(int i = 0; i < 4; i++){
    32         int nx = x + fx[i][0];
    33         int ny = y + fx[i][1];
    34         if(pass(nx,ny)){
    35             vis[nx][ny] = 1;
    36             v.push_back(make_pair(nx,ny));
    37             dfs(nx,ny,v);
    38             v.erase(--v.end());
    39             vis[nx][ny] = 0;
    40         }
    41     }
    42 }
    43 
    44 int main(){
    45     memset(vis, 0, sizeof vis);
    46     vis[0][0] = 1;
    47     for(int i = 0; i < 5; i++){
    48         for(int j = 0; j < 5; j++){
    49             cin>>mp[i][j];
    50         }
    51     }
    52     dfs(0,0,ans);
    53     print(ans);
    54     return 0;
    55 }

    感觉现在写的比以前的还是清晰明了了很多= =

    K-Oil Deposits

    很多人的搜索入门题都是这个题目吧,很经典,就是问有几块油田,一块油田的8个方向内有油田就看为连在一起。

    把遍历过的油田记为*号,都可以把vis数组都省略掉。

    代码如下:

     1 #include <iostream>
     2 #include <cstring>
     3 #include <algorithm>
     4 using namespace std;
     5 
     6 int n,m;
     7 char mp[105][105];
     8 int fx[8][2] = {{1,0},{-1,0},{0,1},{0,-1},{1,1},{1,-1},{-1,1},{-1,-1}};
     9 
    10 bool pass(int x,int y){
    11     if(x < 0 || y < 0 || x >= n || y >= m || mp[x][y] == '*')
    12         return false;
    13     return true;
    14 }
    15 
    16 void dfs(int x,int y){
    17     for(int i = 0; i < 8; i++){
    18         int nx = x + fx[i][0];
    19         int ny = y + fx[i][1];
    20         if(pass(nx,ny)){
    21             mp[nx][ny] = '*';
    22             dfs(nx,ny);
    23         }
    24     }
    25 }
    26 
    27 int main(){
    28     while(cin>>n>>m && n){
    29         int sum = 0;
    30         for(int i = 0; i < n; i++){
    31             for(int j = 0; j < m; j++){
    32                 cin>>mp[i][j];
    33             }
    34         }
    35         for(int i = 0; i < n; i++){
    36             for(int j = 0; j < m; j++){
    37                 if(mp[i][j] == '@'){
    38                     sum++;
    39                     dfs(i,j);
    40                 }
    41             }
    42         }
    43         cout << sum << endl;
    44     }
    45     return 0;
    46 }

    L-非常可乐

    和Pots那个题类似,也是枚举每种状态,但是其实在搜索还可以加上剪枝,例如s为奇数直接输出NO,然后本题还有数学做法,可以自行百度,我不再给出。

    代码如下:

     1 #include <iostream>
     2 #include <cstring>
     3 #include <queue>
     4 #include <algorithm>
     5 using namespace std;
     6 
     7 int s,n,m;
     8 bool vis[105][105][105];
     9 struct node{
    10     int s,n,m,t;
    11 };
    12 
    13 bool check(node n){
    14     if((n.s > 0 && n.n > 0 && n.s == n.n && n.s + n.n == s) || 
    15         (n.s > 0 && n.m > 0 && n.s == n.m && n.s + n.m == s) || 
    16         (n.m > 0 && n.n > 0 && n.m == n.n && n.m + n.n == s))
    17         return true;
    18     return false;
    19 }
    20 
    21 int bfs(){
    22     memset(vis, 0, sizeof vis);
    23     queue<node> q;
    24     q.push(node{s,0,0,0});
    25     vis[s][0][0] = 0;
    26     while(!q.empty()){
    27         node now = q.front();
    28         q.pop();
    29         if(check(now)){
    30             return now.t;
    31         }
    32         node nt = now;
    33         nt.s = now.s - (n-now.n) <= 0 ? 0 : now.s - (n-now.n);
    34         nt.n = now.n + now.s >= n ? n : now.n + now.s;
    35         if(!vis[nt.s][nt.n][nt.m]){
    36             vis[nt.s][nt.n][nt.m] = 1;
    37             nt.t = now.t+1;
    38             q.push(nt);
    39         }
    40         nt = now;
    41         nt.s = now.s - (m-now.m) <= 0 ? 0 : now.s - (m-now.m);
    42         nt.m = now.m + now.s >= m ? m : now.m + now.s;
    43         if(!vis[nt.s][nt.n][nt.m]){
    44             vis[nt.s][nt.n][nt.m] = 1;
    45             nt.t = now.t+1;
    46             q.push(nt);
    47         }
    48         nt = now;
    49         nt.n = now.n - (s-now.s) <= 0 ? 0 : now.n - (s-now.s);
    50         nt.s = now.n + now.s >= s ? s : now.n + now.s;
    51         if(!vis[nt.s][nt.n][nt.m]){
    52             vis[nt.s][nt.n][nt.m] = 1;
    53             nt.t = now.t+1;
    54             q.push(nt);
    55         }
    56         nt = now;
    57         nt.m = now.m - (s-now.s) <= 0 ? 0 : now.m - (s-now.s);
    58         nt.s = now.m + now.s >= s ? s : now.m + now.s;
    59         if(!vis[nt.s][nt.n][nt.m]){
    60             vis[nt.s][nt.n][nt.m] = 1;
    61             nt.t = now.t+1;
    62             q.push(nt);
    63         }
    64         nt = now;
    65         nt.n = now.n - (m-now.m) <= 0 ? 0 : now.n - (m-now.m);
    66         nt.m = now.m + now.n >= m ? m : now.m + now.n;
    67         if(!vis[nt.s][nt.n][nt.m]){
    68             vis[nt.s][nt.n][nt.m] = 1;
    69             nt.t = now.t+1;
    70             q.push(nt);
    71         }
    72         nt = now;
    73         nt.m = now.m - (n-now.n) <= 0 ? 0 : now.m - (n-now.n);
    74         nt.n = now.n + now.m >= n ? n : now.m + now.n;
    75         if(!vis[nt.s][nt.n][nt.m]){
    76             vis[nt.s][nt.n][nt.m] = 1;
    77             nt.t = now.t+1;
    78             q.push(nt);
    79         }
    80     }
    81     return -1;
    82 }
    83 
    84 int main(){
    85     while(cin>>s>>n>>m && s){
    86         int ret = bfs();
    87         if(ret == -1)
    88             cout << "NO" << endl;
    89         else
    90             cout << ret << endl;
    91     }
    92     return 0;
    93 }

    M-Find a way

    这个题我也写过博客,还是我的第一篇题解博客。

    地址链接:https://www.cnblogs.com/xenny/p/9361825.html

    然后这是现在写的代码:

     1 #include <iostream>
     2 #include <queue>
     3 #include <vector>
     4 #include <cstring>
     5 #include <algorithm>
     6 using namespace std;
     7 
     8 char mp[205][205];
     9 int vis[205][205][2];
    10 int fx[4][2] = {0,1,0,-1,-1,0,1,0};
    11 int n,m,yx,yy,mx,my;
    12 struct node{
    13     int x,y;
    14 };
    15 
    16 const int inf = 123456789;
    17 
    18 bool check(int x,int y,int z){
    19     if(vis[x][y][z] != inf || x < 0 || x >= n || y < 0 || y >= m || mp[x][y] == '#')
    20         return false;
    21     return true;
    22 }
    23 
    24 void bfs(int x,int y,int z){
    25     vis[x][y][z] = 0;
    26     queue<node>q;
    27     q.push(node{x,y});
    28     while(!q.empty()){
    29         node now = q.front();
    30         q.pop();
    31         for(int i = 0; i < 4; i++){
    32             int nx = now.x + fx[i][0];
    33             int ny = now.y + fx[i][1];
    34             if(check(nx,ny,z)){
    35                 vis[nx][ny][z] = vis[now.x][now.y][z] + 1;
    36                 q.push(node{nx,ny});
    37             }
    38         }
    39     }
    40 }
    41 
    42 int main(){
    43     while(cin>>n>>m){
    44         fill(vis[0][0], vis[0][0]+205*205*2, inf);
    45         vector< pair<int,int> > v;
    46         for(int i = 0; i < n; i++){
    47             for(int j = 0; j < m; j++){
    48                 cin>>mp[i][j];
    49                 if(mp[i][j] == 'Y')
    50                     yx = i,yy = j;
    51                 if(mp[i][j] == 'M')
    52                     mx = i,my = j;
    53                 if(mp[i][j] == '@')
    54                     v.push_back(make_pair(i,j));
    55             }
    56         }
    57         bfs(yx,yy,0);
    58         bfs(mx,my,1);
    59         int ans = INT_MAX;
    60         for(vector< pair<int,int> >::iterator it = v.begin(); it != v.end(); it++)
    61             ans = min(ans,vis[it->first][it->second][0] + vis[it->first][it->second][1]);
    62         cout << ans*11 << endl;
    63     }
    64 
    65     return 0;
    66 }

    看了以前的博客和现在的,区别还是挺大的,各位也可以尝试用多种方法解决一道题。关于kuangbin专题一的所有题目到此就完了,又不懂的地方可以在评论区留言,同时欢迎指正上面代码的错误。

  • 相关阅读:
    win10安装mongodb教程及其失败解决方案
    基于TypeScript的NodeJs框架:NestJs开发博客API (node.js+nest.js)
    Webpack性能改造之CDN
    44道JavaScript送命题
    electron-vue学习手册
    万字长文带你深度解锁Webpack(进阶篇)
    4W字长文带你深度解锁Webpack系列(上)
    devexpress GalleryControl 获得选中的item并删除
    c# 任意角度旋转图片
    .net core3.1连接GBase数据库的步骤
  • 原文地址:https://www.cnblogs.com/xenny/p/10162457.html
Copyright © 2020-2023  润新知