输入格式
第一行为三个整数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: ",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 ",w); 90 printf("# "); 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 ",ans); 148 return 0; 149 }