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;
}