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;
}
 
                     
                    
                 
                    
                
 
                
            
         
         浙公网安备 33010602011771号
浙公网安备 33010602011771号