題目
10組數據。
每組數據:一個的方陣,每個點上要麼有敵人,要麼有炮臺。
每個炮臺只能夠選擇上,左,右三個方向中的一個。該方向上所有的敵人都被消滅。
問是否存在一種方案,使得所有的敵人被消滅。
數據範圍:
L表示炮臺的個數。
題解
三個套路:
降底數,和普通的貪心。
bitset優化
考慮狀壓,很大,再乘個10跑不過。
考慮將3變成2.
如果每個炮臺只能選擇左,右兩個方向,那麼怎麼消滅所有的敵人?
顯然,如果一行裏有兩個炮臺,那麼這行的敵人全能被消滅。
如果只有1個炮臺,且它在這行的最邊上,那麼這行的敵人也全能被消滅。
因此,枚舉哪個炮臺選擇上的方向,哪些不選擇即可。
bitset維護敵人位置,左右方向的炮臺的位置。
代碼
#include<iostream>
#include<cstdio>
#include<cmath>
#include<algorithm>
#include<cstring>
#include<bitset>
#define N 52
#define fo(i,a,b) for(i=a;i<=b;i++)
using namespace std;
int i,j,k,l,n,m,s,gs,sht,res;
int X[N],Y[N];
int T,cs;
bitset<N>b[N],bt[N],b1[N],b2[N];
bitset<N>L[N],R[N],c1,c2;
int _2[N];
char ch;
bool ia;
int main(){
scanf("%d",&T);
_2[1]=1;
fo(i,2,20)_2[i]=_2[i-1]<<1;
fo(cs,1,T){
scanf("%d%d",&n,&m);
fo(i,1,n){
b[i].reset(),b1[i].reset();
L[i].reset(),R[i].reset();
}
sht=0;ch=0;
ia=0;gs=0;
fo(i,1,n)fo(j,1,m){
ch=getchar();
while((ch^'.')&&(ch^'E')&&(ch^'L'))ch=getchar();
if(ch=='E'){
b[i][j]=1;
sht++;
}
if(ch=='L'){
gs++;
X[gs]=i;
Y[gs]=j;
b1[i][j]=1;
}
}
fo(i,1,n){
fo(j,1,i)L[i][j]=1;
fo(j,i,n)R[i][j]=1;
}
fo(s,0,_2[gs+1]-1){
ia=1;
res=sht;
fo(i,1,n)bt[i]=b[i],b2[i]=b1[i];
fo(i,1,gs)if(s&_2[i]){
b2[X[i]][Y[i]]=0;
fo(j,1,X[i]-1){
if(bt[j][Y[i]]==1){
bt[j][Y[i]]=0;
}
}
}
fo(i,1,gs)if(!(s&_2[i])){
if(b2[X[i]].count()>=2){
bt[X[i]].reset();
continue;
}
c1=bt[X[i]]&L[Y[i]];
c2=bt[X[i]]&R[Y[i]];
if(c1.count()&&c2.count()){
ia=0;
break;
}else bt[X[i]].reset();
}
fo(i,1,n){
if(bt[i].count()){
ia=0;
break;
}
}
if(ia)break;
}
if(ia)printf("Possible\n");else printf("Impossible\n");
}
return 0;
}