2019年6月28日、学校のテストT1ゼリー問題1

この質問は(私は説明が右ではなく、説明に従って実際にACを行うと思いますが)問題の意味の説明のその部分に直接ジャンプすることが推奨され、理解することは少し難しい直面しています。

よる「質問の意味を説明し、」この問題を考えるためのアイデアは、それは非常に簡単です:

1.まず、この文字行列を読み取るには、CINを(TLEが知ることができません)、ここで私はgetchar関数は読み込み使用使用することができます。

2.「*」全体の検索は、すべての点がトラバースされるまで、それぞれの「#」は、時間に検索されているもの記録、再び始まったから。

3.最大時間のすべての「#」の位置を検索し、最初の質問は、できるだけ多く記録された時間のために、答えです。

4.それが最短時間t横切る場合、単位時間当たりの格子は、特定のグリッドiについてように、一点の高さによって増加するためを通じてIを、その寄与答えは:はるか- T I + 1、意志各グリッドの寄与は、最大追加2番目の質問、それに対する答えです。

5.解決策が決定されていない場合を考える:O(nm)の時間は、溶液の全く発生しないことを示す場合(トラバースされていないグリッド)、0を横断する場合、暴力的な全ての格子をスキャン。

コードは以下の通りであります:

#include<iostream>
#include<cstdio>
#include<queue>
#include<cmath>
using namespace std;
const int mod=19260817;
char read()                              //自定义字符读入 
{
    char ch=getchar();
    while(ch!='*'&&ch!='o'&&ch!='#') ch=getchar();  //不是题目中的三种字符就一直往下读 
    return ch;
}
struct juanzi                            //开一个结构体,存每一个格子的信息:最先被遍历的时间是t,坐标是(x1,y1) 
{
    int t,x1,y1;
}b[250001];              
queue<juanzi> q;                         //开一个结构体类型的队列 
char a[501][501];                        //存输入的字符矩阵 
int n,m,start,endd,xx,yy;                //n*m的矩阵,打印机'*'的坐标是(start,endd),注意不要用end,好像会和STL里面的东西重名(我CE我知道) 
int dx[5]={0,1,0,-1,0};                  //四个方向 
int dy[5]={0,0,-1,0,1};
int vis[501][501];                       //存每个点被遍历的时间 
int ans,much;     
void bfs()         
{
    q.push((juanzi){0,start,endd});      //起点入队 
    juanzi f;
    while(!q.empty())                    //其实我们每一步都判断是否将所有点都遍历过,只需判队列非空就好啦,队列为空就说明无法再遍历到其他的点了 
    {
        f=q.front();                     
        q.pop();
        for(int i=1;i<=4;i++)
        {
            xx=f.x1+dx[i];               //往四个方向走 
            yy=f.y1+dy[i];
            if(a[xx][yy]=='#'&&vis[xx][yy]==0)   //如果可以走并且之前没走过,那就走 
            {
                vis[xx][yy]=f.t+1;       //到这个格子的时间是上一个格子的时间再加一 
                q.push((juanzi){f.t+1,xx,yy});   //入队去遍历下面的格子 
            }    
        }
    }
}
int main()
{
    scanf("%d%d",&n,&m);
    for(int i=1;i<=n;i++)
       for(int j=1;j<=m;j++)
          {
                a[i][j]=read();
                if(a[i][j]=='*')           //记录下打印机'*'的位置 
                {
                        start=i;                  
                    endd=j; 
                    vis[i][j]=-1;        //把不能遍历的点的时间全赋成-1 
              }
              if(a[i][j]=='o') vis[i][j]=-1;    //花盆的位置      
          }
    bfs();                               //核心代码:广度优先搜索
    for(int i=1;i<=n;i++)                //判无解的情况 
       for(int j=1;j<=m;j++)
          if(vis[i][j]==0) 
          {
              cout<<-1;return 0;
          } 
    for(int i=1;i<=n;i++)
       for(int j=1;j<=m;j++)
          much=max(much,vis[i][j]);      //找最后被遍历到的点所需要的时间 
    printf("%d\n",much);
    for(int i=1;i<=n;i++)
       for(int j=1;j<=m;j++)
       {
              if(vis[i][j]>0)               //排除了打印机'*'和花盆'o'的位置 
              {
                      ans=(ans+(much-vis[i][j]+1)%mod)%mod;  //每个格子的贡献 
           }
       }
    printf("%d",ans);
    return 0;
}
/*
其实由于数据有锅,无解的情况没有看出来,当成有解的情况做了;
AC代码要注释掉那个判断无解的情况QwQ~
但加上那一段判无解的代码应该才是最正确的 
*/

 

おすすめ

転載: www.cnblogs.com/xcg123/p/11105602.html