bzoj2755【SCOI2012】喵星人的入侵

输入格式

第一行为三个整数n,m,K,分别表示地图的长和宽,以及最多能放置的炮塔数量。 
接下来的n行,每行包含m个字符,‘#’表示地图上原有的障碍,‘.’表示该处为空地,
数据保证在原地图上存在S到T的路径。 


输出格式

输出在合理布阵下,喵星人采取最优策略后,会受到的最大伤害。 
注意必须保证在布阵结束后喵星人仍然可以沿一条或以上的路径从起点S到达终点T,
否则他们组织更大规模的侵略。 


 

提示

 

【数据范围】 
对于30%的数据,保证:
1<=N,M<=6
对于100%的数据,保证:
1<=N<=6,1<=M<=20,1<=K<=15,且从S到T的路径必定存在。


 

  • 题解:

    • 由于可以无限放置障碍,所以最后一定只会有一条路径;
    • 插头$dp$求出路径即可;
    • 注意和普通路径不同,路径不能组成四连通块;
  1 #include<bits/stdc++.h>
  2 #define il inline 
  3 #define rg register 
  4 using namespace std;
  5 const int N=10,M=21,sz=1e5;
  6 int n,m,K,c1[N],c2[N],cur,ans;
  7 char s[M][M];
  8 struct HASH{
  9     int o,hd[sz],v[sz],w[sz],nt[sz];
 10     il void init(){for(int i=1;i<=o;++i)hd[v[i]%sz]=0,v[i]=w[i]=nt[i]=0;o=0;}
 11     il void upd(int x,int y){
 12         for(rg int i=hd[x%sz];i;i=nt[i])if(v[i]==x){
 13             if(w[i]<y)w[i]=y;
 14             return;
 15         }
 16         nt[++o]=hd[x%sz],hd[x%sz]=o,v[o]=x,w[o]=y;
 17     }
 18 }f[2][M];
 19 il void upd(int&x,int y){if(x<y)x=y;}
 20 il void decode(int x){
 21     for(rg int i=0;i<=m;++i)c1[i]=x&3,x>>=2;
 22     for(rg int i=0;i<=m;++i)c2[i]=x&3,x>>=2;
 23 }
 24 il int encode(){
 25     int x=0;
 26     for(rg int i=m;~i;--i)x=(x<<2)^c2[i];
 27     for(rg int i=m;~i;--i)x=(x<<2)^c1[i];
 28     return x;
 29 }
 30 il int le(int x){
 31     for(rg int i=x,y=0;~i;--i)if(c1[i]&&c1[i]!=3){
 32         y+=(c1[i]&1)?1:-1;
 33         if(!y)return i;
 34     }return 0;
 35 }
 36 il int ri(int x){
 37     for(rg int i=x,y=0;i<=m;++i)if(c1[i]&&c1[i]!=3){
 38         y+=(c1[i]&1)?1:-1;
 39         if(!y)return i;
 40     }return 0;
 41 }
 42 il int cal1(int x){
 43     int l=max(x-1,0),r=min(x+2,m),re=0;
 44     for(rg int i=l;i<=r;++i)if(c2[i]==1)re++;
 45     return re;
 46 }
 47 il int cal2(int x){
 48     int l=max(x-1,0),r=min(x+2,m),re=0;
 49     for(rg int i=l;i<=r;++i)if(c2[i]==2)re++;
 50     return re;
 51 }
 52 il bool check(int j){
 53     for(rg int i=0;i<=m;++i)if(i!=j&&i!=j+1&&c1[i])return false;
 54     return true;
 55 }
 56 int main(){
 57     #ifndef ONLINE_JUDGE
 58     freopen("C.in","r",stdin);
 59     freopen("C.out","w",stdout);
 60     #endif
 61     scanf("%d%d%d",&n,&m,&K);
 62     for(rg int i=0;i<n;++i)scanf("%s",s[i]);
 63     if(n<m){
 64         for(rg int i=0;i<n;++i)
 65         for(rg int j=i+1;j<m;++j){
 66             swap(s[i][j],s[j][i]);
 67         }
 68         swap(n,m);
 69     }
 70     f[cur=0][0].upd(0,0);
 71     for(rg int i=0;i<n;++i)
 72     for(rg int j=0;j<m;++j){
 73         for(rg int k=0;k<=K;++k){
 74             for(rg int l=1;l<=f[cur][k].o;++l){
 75                 int w=f[cur][k].w[l];
 76                 decode(f[cur][k].v[l]);
 77                 if(!j){
 78                     if(c1[m])continue;
 79                     for(rg int i=m;i;--i)c1[i]=c1[i-1],c2[i]=c2[i-1];
 80                     c1[0]=c2[0]=0;
 81                 }
 82                 /*
 83                 { 
 84                     printf("%d %d %d:\n",i,j,k);
 85                     for(int i=0;i<=m;++i)printf("%d ",c1[i]);
 86                     puts("");
 87                     for(int i=0;i<=m;++i)printf("%d ",c2[i]);
 88                     puts("");
 89                     printf("%d\n",w);
 90                     printf("#\n");
 91                 }*/
 92                 
 93                 int &p=c1[j],&q=c1[j+1],&r=c2[j],w1=w+cal1(j),w2=w+cal2(j);
 94                 int t1=j&&(c2[j-1]&1),t2=j!=m&&(c2[j+1]&1);
 95                 if(s[i][j]=='#'){
 96                     if(p||q)continue;
 97                     r=0,f[cur^1][k].upd(encode(),w);
 98                 }else if(!p&&!q){
 99                     if(s[i][j]=='.'){
100                         p=0,q=0;
101                         r=0,f[cur^1][k].upd(encode(),w);
102                         if(k<K)r=2,f[cur^1][k+1].upd(encode(),w1);
103                     }
104                     if(t1||t2)continue;
105                     if(s[i][j]=='S'||s[i][j]=='T'){
106                         p=3,q=0,r=1,f[cur^1][k].upd(encode(),w2);
107                         p=0,q=3,r=1,f[cur^1][k].upd(encode(),w2);
108                     }else p=1,q=2,r=1,f[cur^1][k].upd(encode(),w2);
109                 }else if(!p||!q){
110                     if(t1&&t2)continue;
111                     if(s[i][j]=='S'||s[i][j]=='T'){
112                         if(p+q!=3){
113                             if(p+q==1)c1[ri(j)]=3;else c1[le(j+1)]=3;
114                             p=q=0,r=1,f[cur^1][k].upd(encode(),w2);
115                         }
116                         else if(check(j))p=0,q=0,r=1,f[cur^1][k].upd(encode(),w2);
117                     }else{
118                         r=1,swap(p,q),f[cur^1][k].upd(encode(),w2);
119                         r=1,swap(p,q),f[cur^1][k].upd(encode(),w2);
120                     }
121                 }else{
122                     if(p==3&&q==3){
123                         p=q=0,r=1,f[cur^1][k].upd(encode(),w2);
124                     }else if(p==3||q==3){
125                         if(p+q-3==1)c1[ri(j)]=3;
126                         else if(p+q-3==2)c1[le(j+1)]=3;
127                         p=q=0,r=1,f[cur^1][k].upd(encode(),w2);
128                     }else {
129                         if(p==1&&q==2)continue;
130                         if(p==q){
131                             if(p==1)c1[ri(j+1)]=1;
132                             else c1[le(j)]=2;
133                         }
134                         p=q=0,r=1,f[cur^1][k].upd(encode(),w2);
135                     }
136                 }
137             }
138             f[cur][k].init();
139         }
140         cur^=1;    
141     }
142     for(int i=1;i<=K;++i)
143     for(int j=1;j<=f[cur][i].o;++j){
144         decode(f[cur][i].v[j]);
145         if(check(m+1))upd(ans,f[cur][i].w[j]);
146     }
147     printf("%d\n",ans);
148     return 0;
149 }
View Code

 

posted @ 2019-02-25 21:29  大米饼  阅读(367)  评论(0编辑  收藏  举报