2018年徐州赛区A. Plague Inc

A. Plague Inc

Plague Inc. is a famous game, which player develop virus to ruin the world.

JSZKC wants to model this game. Let's consider the world has N*M cities. The world has N rows
and M columns. The city in the X rows and the Y column has coordinate (X,Y).

There are K cities which are sources of infection at the 0_th day.Each day the infection in any infected city will spread to the near four cities (if exist).

JSZKC wants to know which city is the last one to be infected. If there are more than one cities , answer the one with smallest X firstly, smallest Y secondly.


Input Format


The input file contains several test cases, each of them as described below.

The first line of the input contains two integers N and M  (1 ≤ N,M ≤ 2000), giving the number of rows and columns of the world.
The second line of the input contain the integer K (1≤K≤10).
Then K lines follow. Each line contains two integers X_i and Y_i, indicating (X_i,Y_i) is a source. It's guaranteed that the coordinates are all different.
There are no more than 20 test cases.


Output Format


For each testcase, output one line with coordinate X and Y separated by a space.



样例输入


3 3
1
2 2
3 3
2
1 1
3 3



样例输出


1 1
1 3
 


「小结」:

本来我以为这个题有什么坑之类的,我真没想到当时学长为什么错了这么多遍还是过不了。

「题意」:

这个题目背景设立在一个游戏吧,之前看我同学玩过,但是这个名字我真记不住,

但是这个题目就是这样一个设置吧。就是每一秒都会延伸四个方向,

问最后的哪一个格子是最后的,如果答案有多个,那么输出最小的那一个行标,列标。

暴力很稳:

#include<bits/stdc++.h>
using namespace std;
typedef pair<int,int> PII;
const int N=2e3+10;
int n,m,q,vis[N][N];
int main()
{
    while(~scanf("%d%d",&n,&m)){
        memset(vis,127,sizeof(vis));
        scanf("%d",&q);
        PII *a = new PII[20];
        for(int i=0;i<q;i++){
            int x,y;
            scanf("%d%d",&x,&y);
            a[i]=make_pair(x,y);
            vis[x][y]=1;
        }
        /*for(int i=0;i<q;i++){
            printf("%d %d \n",a[i].first,a[i].second);
        }*/
        int ans=-1;
        for(int i=1;i<=n;i++){
            for(int j=1;j<=m;j++){if(vis[i][j]!=1)
                for(int k=0;k<q;k++){
                    int tmp=abs(a[k].first-i)+abs(a[k].second-j);
                    vis[i][j]=min(vis[i][j],tmp);
                }

            }
        }
        /*for(int i=1;i<=n;i++){
            for(int j=1;j<=m;j++){
                printf("%d%c",vis[i][j],j==m?'\n':' ');
            }
        }*/
        int ansx=0,ansy=0;
        for(int i=1;i<=n;i++){
            for(int j=1;j<=m;j++){
                if(vis[i][j]>ans){
                    ansx=i;
                    ansy=j;
                    ans=vis[i][j];
                }
            }
        }
        printf("%d %d\n",ansx,ansy);
    }
    return 0;
}

做这道题的本意其实是试一下,模拟队列来的:后来还是超时。看过别人代码才醒悟了一点。

模拟队列

#include<bits/stdc++.h>
using namespace std;
const int N=2e3+10;
typedef pair<int,int> PII;
template <class T>
inline void read(T &x){
    x=0;int f=1;char c=getchar();
    for( ; !isdigit(c);c=getchar()){ if(c=='-') f=-1;}
    for( ;  isdigit(c);c=getchar()){ x=x*10+c-'0';}x*=f;
}
PII a[55];
int n,m,k,x,y,head,tail,sum,vis[N][N];
int dir[4][2]={
        {-1,0},
    {0,-1}, {0,1},
        {1,0}
};
inline bool judge(int x,int y){
    if(x<1||y<1||x>n||y>m){
        return false;
    }return true;
}
PII q[N*N];
int main()
{
    while(~scanf("%d%d",&n,&m)){
        read(k);
        head=tail=1;
        memset(vis,0,sizeof(vis));
        for(int i=0;i<k;i++){
            read(x),read(y);
            q[tail++]=make_pair(x,y);
            vis[x][y]=1;
        }
        sum=k;
        k=0;
        while(sum<n*m){
            int tot=tail-head;
            while(tot--){
                x=q[head].first,y=q[head].second;
                head++;
                for(int i=0;i<4;i++){
                    int tx=x+dir[i][0];
                    int ty=y+dir[i][1];
                    if(judge(tx,ty)&&vis[tx][ty]==0){
                        sum++;
                        vis[tx][ty]=vis[x][y]+1;
                        k=max(vis[tx][ty],k);
                        q[tail++]=make_pair(tx,ty);
                    }
                }
            }
        }
        /*for(int i=1;i<=n;i++){
            for(int j=1;j<=m;j++){
                printf("%d%c",vis[i][j],j==m?'\n':' ');
            }
        }*/
        PII ans=q[head];
        while(head<tail){
            if(ans.first>q[head].first){
                ans=q[head];
            }else if(ans.first==q[head].first&&ans.second>q[head].second){
                ans=q[head];
            }
            head++;
        }
        printf("%d %d\n",ans.first,ans.second);
    }
    return 0;
}

换了一种写法。差不多,但是今天有学会了一点优化,手写判断方向,函数多次调用会堆栈,时间很长。

手写方向判断:

#include<bits/stdc++.h>
using namespace std;
const int N=2e3+10;
typedef pair<int,int> PII;
template <class T>
inline void read(T &x){
    x=0;int f=1;char c=getchar();
    for( ; !isdigit(c);c=getchar()){ if(c=='-') f=-1;}
    for( ;  isdigit(c);c=getchar()){ x=x*10+c-'0';}x*=f;
}
PII a[55];
int n,m,k,x,y,head,tail,sum,vis[N][N];
int dir[4][2]={
        {-1,0},
    {0,-1}, {0,1},
        {1,0}
};
inline bool judge(int x,int y){   //手写还是挺快的,不要常用方向数组。
                                   //居然可以快0.5s惊人的数据
    if(x<1||y<1||x>n||y>m){
        return false;
    }return true;
}
queue<PII>q;
int main()
{
    while(~scanf("%d%d",&n,&m)){

        read(k);
        head=tail=1;
        memset(vis,0,sizeof(vis));
        for(int i=0;i<k;i++){
            read(x),read(y);
            q.push(make_pair(x,y));
            vis[x][y]=1;
        }
        sum=k;
        k=0;
        while(sum<n*m){
            int tot=q.size();
            while(tot--){
                x=q.front().first,y=q.front().second;
                q.pop();
                if(x+1<=n&&!vis[x+1][y]){
                    vis[x+1][y]=1;sum++;
                    q.push(make_pair(x+1,y));
                }
                if(x-1>=1&&!vis[x-1][y]){
                    vis[x-1][y]=1;sum++;
                    q.push(make_pair(x-1,y));
                }
                if(y+1<=m&&!vis[x][y+1]){
                    vis[x][y+1]=1;sum++;
                    q.push(make_pair(x,y+1));
                }
                if(y-1>=1&&!vis[x][y-1]){
                    vis[x][y-1]=1;sum++;
                    q.push(make_pair(x,y-1));
                }
            }
        }
        /*for(int i=1;i<=n;i++){
            for(int j=1;j<=m;j++){
                printf("%d%c",vis[i][j],j==m?'\n':' ');
            }
        }*/
        PII ans=q.front();
        while(!q.empty()){
            if(ans.first>q.front().first){
                ans=q.front();
            }else if(ans.first==q.front().first&&ans.second>q.front().second){
                ans=q.front();
            }
            q.pop();
        }
        printf("%d %d\n",ans.first,ans.second);
    }
    return 0;
}

 

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值