Codeforces 254D

题目链接:http://acm.hust.edu.cn/vjudge/problem/37171

题目大意:

给出一个n*m的矩阵,分为墙和空地,有的空地上有老鼠,你有两颗手雷(!),可以放置在不同的两块空地上,手雷爆炸后消灭一定范围内的老鼠(冲击波具体传播方式看原题),求能否消灭全部老鼠。

分析:

相比矩阵大小,我们发现手雷的爆炸范围特别小,每个手雷最多炸到145个格子,即最多炸死145只老鼠,两个手雷最多炸死290个,所以老鼠数量大于290时必定无解,这样我们就把老鼠数量缩小到了290以内。

枚举两个手雷位置太慢了,我们不妨枚举每只老鼠,求出所有放置手雷能炸死它的格子,最后总格子数也不多(290*145),且很多是重复的。

然后就在所选格子中枚举两个,看它们能否炸死全部的。

时间很玄学,反正跑得快。

#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <algorithm>
#include <vector>
#include <queue>

#define rep(i,x,y) for (int i=x;i<=y;i++)
#define dep(i,y,x) for (int i=y;i>=x;i--)
#define sz(x) ((int)(x.size()))

using namespace std;

const int maxn=1000+24,maxr=300;
const int dx[4]={-1,0,1,0},dy[4]={0,1,0,-1};

int size,n,m,d,x,y,k,cnt,p,q,vx[maxr*maxr],vy[maxr*maxr];

bool mark,M[maxn][maxn],vis[maxn][maxn],v[maxr*maxr][maxr],reach[maxn][maxn];

char s[maxn][maxn];

vector<pair<int,int> > rat;

struct node{
  int x,y,d;
  node(int x,int y,int d):x(x),y(y),d(d) {}
};

void insert(int x,int y,int k) //将当前手雷备选点插入
{
 if (!reach[x][y]) 
 {
  size++;
  v[size][k]=1,vx[size]=x,vy[size]=y;
  return;
 }

 rep(i,1,size)
  if ((vx[i]==x)&&(vy[i]==y)) {v[i][k]=1;return;}
}

void solve(int t,int x,int y)
{
 memset(vis,0,sizeof(vis));
 
 queue<node> Q;
 Q.push(node(x,y,0));

 while (!Q.empty())
 {
  node k=Q.front();Q.pop();

  vis[k.x][k.y]=1,insert(k.x,k.y,t),reach[k.x][k.y]=1;

  if (k.d==d) continue;
  
  rep(i,0,3)
  {
   int a=k.x+dx[i],b=k.y+dy[i];
   if ((!vis[a][b])&&(!M[a][b])) Q.push(node(a,b,k.d+1));
  }
 }

}

void init()
{
 cnt=0,size=0;
 rat.clear();
 memset(reach,0,sizeof(reach));
 memset(v,0,sizeof(v));
}

int main()
{
 freopen("input.txt","r",stdin);
 freopen("output.txt","w",stdout);

 scanf("%d%d%d",&n,&m,&d);
 
 init();

 rep(i,1,n)
 {
  scanf("%s",s[i]+1);
  rep(j,1,m)
   if (s[i][j]=='R') cnt++;
 }

 if (cnt>maxr) {printf("%d\n",-1);return 0;} //老鼠太多
 
 rep(i,1,n)
  rep(j,1,m)
  {
   M[i][j]=0;
   if (s[i][j]=='R') rat.push_back(make_pair(i,j)); //记录老鼠位置
   if (s[i][j]=='X') M[i][j]=1;
  }
 
 rep(i,0,sz(rat)-1)
  solve(i,rat[i].first,rat[i].second); //BFS求各个老鼠范围
 
 if (size==1) //注意特判!
 {
  rep(k,0,sz(rat)-1)
   if (!v[1][k]) {printf("%d\n",-1);return 0;}

  printf("%d %d",vx[1],vy[1]);

  rep(i,1,n)
   rep(j,1,m)
    if ((!M[i][j])&&(!((i==vx[1])&&(j==vy[1])))) {printf(" %d %d\n",i,j);return 0;}
 }

 rep(i,1,size-1) //枚举两个位置
 {
  rep(j,i+1,size)
  {
   mark=1;
   rep(k,0,sz(rat)-1)
    if ((v[i][k]==0)&&(v[j][k]==0)) {mark=0;break;}
   if (mark) {p=i,q=j;break;}
  }
  if (mark) break;
 }

 if (mark) 
  printf("%d %d %d %d\n",vx[p],vy[p],vx[q],vy[q]); 
 else 
  printf("%d\n",-1);
 
 return 0;
}

posted @ 2016-07-23 10:19  Krew  阅读(148)  评论(0)    收藏  举报