zoukankan      html  css  js  c++  java
  • 洛谷 P3956 棋盘(BFS)

    传送门:Problem P3956

    https://www.cnblogs.com/violet-acmer/p/9827010.html

    题解:

      BFS

      相关变量解释:

        color[maxn][maxn];...................................color[ i ][ j ] : ( i , j )点的颜色,-1代表无色
        dp[maxn][maxn];.......................................dp[ i ][ j ] : 从( 1 , 1 )点到( i , j )点需要花费的最少金币
        magic[maxn][maxn];..................................magic[ i ][ j ] : 判断 ( i , j )点是否使用魔法
        in[maxn][maxn];.........................................in[ i ][ j ] : 判断( i , j )点是否在队列中

      具体步骤:

        初始,将(1,1)点加入队列中;

        (1):保存队头元素并弹出

        (2):每次,判断当前点的上下左右点是否可以通过当前点使dp[ ][ ]变小,如果可以,更新dp[ ][ ],如果被更新的点不在队列中,加入队列

        (3):重复(2)过程,直到队列为空

    AC代码:

      1 #include<iostream>
      2 #include<cstdio>
      3 #include<queue>
      4 #include<cstring>
      5 using namespace std;
      6 #define INF 0x3f3f3f3f
      7 #define P pair<int ,int >
      8 #define mem(a,b) memset(a,b,sizeof a)
      9 const int maxn=100+50;
     10 
     11 int m,n;
     12 int color[maxn][maxn];
     13 int dp[maxn][maxn];
     14 bool marge[maxn][maxn];
     15 bool in[maxn][maxn];
     16 queue<P >myqueue;
     17 int dx[4]={-1,1,0,0};
     18 int dy[4]={0,0,-1,1};
     19 bool isSat(int val)
     20 {
     21     return val >= 1 &&val <= m;
     22 }
     23 void Solve()
     24 {
     25     dp[1][1]=0;//初始化dp[1][1],并将其加入到队列中
     26     myqueue.push(P(1,1));
     27     while(!myqueue.empty())//步骤(3)
     28     {
     29         P p=myqueue.front();//步骤(1)
     30         myqueue.pop();
     31         in[p.first][p.second]=false;
     32         for(int i=0;i < 4;++i)//步骤(2)
     33         {
     34             int x=p.first+dx[i];
     35             int y=p.second+dy[i];
     36             if(isSat(x) && isSat(y))
     37             {
     38                 if(!marge[p.first][p.second])//如果当前点的未使用过魔法的,也就意味这当前点的颜色是本身就有的
     39                 {
     40                     if(!marge[x][y])//如果与当前点相邻的点(x,y)也为曾使用过魔法
     41                     {
     42                         if(color[x][y] != -1)//如果点(x,y)有色,但并不是因为魔法而产生的
     43                         {
     44                             //如果当前点可以放缩dp[x][y]
     45                             if(dp[x][y] > dp[p.first][p.second]+(color[x][y] != color[p.first][p.second]))
     46                             {
     47                                 dp[x][y]=dp[p.first][p.second]+(color[x][y] != color[p.first][p.second]);
     48                                 if(!in[x][y])//被放缩的点(x,y)如果不在队列中,加入队列
     49                                     in[x][y]=true,myqueue.push(P(x,y));
     50                             }
     51                         }
     52                         else//如果无色,通过使用魔法将其变为与当前点颜色相同的点,并被放缩了dp[][]
     53                         {
     54                             marge[x][y]=true;
     55                             color[x][y]=color[p.first][p.second];
     56                             dp[x][y]=dp[p.first][p.second]+2;
     57                             if(!in[x][y])
     58                                 in[x][y]=true,myqueue.push(P(x,y));
     59                         }
     60                     }
     61                     else if(dp[x][y] > dp[p.first][p.second]+2)//如果点(x,y)在之前使用过魔法,就需要判断,当前为使用过魔法的点是否可以放缩dp[x][y]
     62                     {
     63                         dp[x][y]=dp[p.first][p.second]+2;
     64                         color[x][y]=color[p.first][p.second];
     65                         if(!in[x][y])
     66                             in[x][y]=true,myqueue.push(P(x,y));
     67                     }
     68                 }
     69                 else if(!marge[x][y] && color[x][y] != -1)//如果当前点的使用过魔法的,也就意味这当前点的颜色是通过魔法变来的,那么,只有当其临近点(x,y)含有的颜色是其本身就有的才有资格判断是否可以被放缩
     70                 {
     71                     if(dp[x][y] > dp[p.first][p.second]+(color[x][y] != color[p.first][p.second]))
     72                     {
     73                         dp[x][y]=dp[p.first][p.second]+(color[x][y] != color[p.first][p.second]);
     74                         if(!in[x][y])
     75                             myqueue.push(P(x,y)),in[x][y]=true;
     76                     }
     77                 }
     78             }
     79         }
     80     }
     81     printf("%d
    ",dp[m][m] == INF ? -1:dp[m][m]);
     82 }
     83 void Init()
     84 {
     85     mem(dp,INF);
     86     mem(in,false);
     87     mem(marge,false);
     88     mem(color,-1);
     89 }
     90 int main()
     91 {
     92     scanf("%d%d",&m,&n);
     93     Init();
     94     for(int i=1;i <= n;++i)
     95     {
     96         int x,y;
     97         scanf("%d%d",&x,&y);
     98         scanf("%d",&color[x][y]);
     99     }
    100     Solve();
    101 }
    View Code

      

  • 相关阅读:
    python学习第十一天 -- 函数式编程
    python学习第十天 -- 函数
    python学习第九天 -- 列表生产式
    python学习第八天 -- 迭代
    (转载)C# 编程 使用可空类型
    Func的介绍——c#封装的代理
    select SCOPE_IDENTITY()用法
    insert into 语句的三种写法
    面试感悟----一名3年工作经验的程序员应该具备的技能
    SQL中常用模糊查询的四种匹配模式&&正则表达式
  • 原文地址:https://www.cnblogs.com/violet-acmer/p/9827205.html
Copyright © 2011-2022 走看看