转载请注明出处,谢谢http://blog.csdn.net/ACM_cxlove?viewmode=contents by---cxlove
题目:给出一个地图,某些位置有一些老鼠,有两个炸弹,攻击范围每一秒都能向4个方向扩散,不能穿过墙。炸弹会在d秒后爆炸,问是否能找到两个位置,放置炸弹,能炸死所有老鼠(= = 大概意思就这样
首先把所有的R找出来,可以通过R的个数剪枝一次。
我们可以发现d其实是很小的,也许这是一个突破口吧
每一个炸弹极限情况下能在d秒扩散的范围是可以算出来,就是一个菱形的东东吧。
那么两个炸弹最多覆盖的范围也可以算出来,这里可以 小剪一下。对于R很多的情况,直接pass掉了,good
那么再考虑可行的范围,一个炸弹能到达的位置,肯定是曼哈顿距离小于d
以每只老鼠为中心,先把所有可行的点拿出来(= =至少得覆盖一只老鼠才会开始考虑吧
其实这里也是可以剪枝一下的,我们考虑当一个炸弹扩散,最极端的情况是,最外面一圈是炸弹,然后再用最外面一圈去扩散,相当于炸弹扩散2*d次,可以算出最多有多少个位置可行,那么如果可行的位置过多,说明老鼠过于分散,也是不可行。
然后对于可行解去BFS,记录能到达哪些老鼠,对于每一个可能的可行解都用set记录了到达的老鼠标号。
最后两两枚举,合并set,判断是否能搞定所有老鼠。
TLE了好久,加上一个小剪枝就过了,果然是合并set太矬了
其实复杂度是可行的
BFS的状态数目最多大概为226吧,那个可能可行解上限大概是1200左右
#include<iostream>
#include<cstdio>
#include<map>
#include<cstring>
#include<cmath>
#include<vector>
#include<algorithm>
#include<set>
#include<string>
#include<queue>
#define inf 1600005
#define M 40
#define N 1005
#define maxn 2000005
#define eps 1e-7
#define zero(a) fabs(a)<eps
#define Min(a,b) ((a)<(b)?(a):(b))
#define Max(a,b) ((a)>(b)?(a):(b))
#define pb(a) push_back(a)
#define mp(a,b) make_pair(a,b)
#define mem(a,b) memset(a,b,sizeof(a))
#define LL long long
#define MOD 1000000007
#define lson step<<1
#define rson step<<1|1
#define sqr(a) ((a)*(a))
#define Key_value ch[ch[root][1]][0]
#define test puts("OK");
#define pi acos(-1.0)
#define lowbit(x) ((x)&(-(x)))
#pragma comment(linker, "/STACK:1024000000,1024000000")
#define vi vector<int>
using namespace std;
int row,col,d;
char str[N][N];
vector<pair<int,int> >rat,tmp;
int p[N][N];
set<int>s[N];
int way[4][2]={0,1,0,-1,1,0,-1,0};
bool flag[N][N];
bool check(int x,int y){
if(x>=0&&y>=0&&x<row&&y<col&&str[x][y]!='X')
return true;
return false;
}
int main(){
freopen("input.txt","r",stdin);
freopen("output.txt","w",stdout);
while(scanf("%d%d%d",&row,&col,&d)!=EOF){
rat.clear();mem(p,-1);
for(int i=0;i<row;i++){
scanf("%s",str[i]);
for(int j=0;j<col;j++)
if(str[i][j]=='R'){
rat.pb(mp(i,j));
p[i][j]=rat.size();
}
}
//剪枝,两个位置,扩展d次,可以算出最多覆盖多少个格子
int t=d+1;
if(rat.size()>2*(2*sqr(t)-2*t+1)){
puts("-1");
continue;
}
for(int i=0;i<rat.size();i++){
for(int j=-d;j<=d;j++){
for(int k=-d;k<=d;k++){
if(abs(j)+abs(k)>d) continue;
int x=rat[i].first+j;
int y=rat[i].second+k;
if(check(x,y)) tmp.pb(mp(x,y));
}
}
}
sort(tmp.begin(), tmp.end());
int size=unique(tmp.begin(), tmp.end())-tmp.begin();
t*=2;
if(size> 2*(2*sqr(t)-2*t+1) ){
puts("-1");
continue;
}
for(int i=0;i<size;i++){
queue<pair<pair<int,int>,int> >que;
while(!que.empty()) que.pop();
mem(flag,false);
flag[tmp[i].first][tmp[i].second]=true;
que.push(mp(mp(tmp[i].first,tmp[i].second),0));
while(!que.empty()){
pair<pair<int,int>,int>u=que.front(),v;
que.pop();
if(str[u.first.first][u.first.second]=='R')
s[i].insert(p[u.first.first][u.first.second]);
if(u.second>=d) continue;
for(int i=0;i<4;i++){
v=u;
v.first.first+=way[i][0];
v.first.second+=way[i][1];
v.second+=1;
if(check(v.first.first,v.first.second)&&!flag[v.first.first][v.first.second]){
flag[v.first.first][v.first.second]=true;
que.push(v);
}
}
}
}
bool ans=false;
for(int i=0;i<size&&!ans;i++){
for(int j=i+1;j<size&&!ans;j++){
//唔,这个剪枝,直接从T到100ms,果然我乱用set太慢了
if(s[i].size()+s[j].size()<rat.size()) continue;
set<int>temp(s[i]);
for(set<int>::iterator it=s[j].begin();it!=s[j].end();it++)
temp.insert(*it);
if(temp.size()==rat.size()){
ans=true;
printf("%d %d %d %d\n",tmp[i].first+1,tmp[i].second+1,tmp[j].first+1,tmp[j].second+1);
}
}
}
if(!ans) puts("-1");
for(int i=0;i<size;i++) s[i].clear();
}
return 0;
}