【CF845F】Guards In The Storehouse 插頭DP
阿新 • • 發佈:2018-01-14
namespace return scan printf swa 超過 障礙 body pri
【CF845F】Guards In The Storehouse
題意:一個n*m的房間,每個格子要麽是障礙要麽是空地。對於每個空地你可以選擇放或者不放守衛。一個守衛能保護到的位置是:他右面的一行空地+下面的一列空地,但是不能穿過障礙(可以穿過另一個守衛)。現在要求至多有1個空地沒有被保護,求放置守衛的方案數。
$n\times m\le 250$
題解:n和m中較小者不超過15,所以插頭DP不解釋~
#include <cstdio> #include <cstring> #include <iostream> using namespace std; const int P=1000000007; int f[2][(1<<16)+1][2]; int n,m,msk,ans; char str[255][255]; inline void upd(int &x,int y) {x+=y; if(x>=P) x-=P;} int main() { scanf("%d%d",&n,&m); int i,j,d=0,S,T,p,q,x,y,v0,v1; for(i=0;i<n;i++) scanf("%s",str[i]); if(n<m) { for(i=0;i<n;i++) for(j=i;j<m;j++) swap(str[i][j],str[j][i]); swap(n,m); } msk=(1<<(m+1))-1,f[0][0][0]=1; for(i=0;i<n;i++) { for(j=0;j<m;j++) { d^=1,memset(f[d],0,sizeof(f[d])); for(S=0;S<=msk;S++) { x=j,y=j+1,p=(S>>x)&1,q=(S>>y)&1,T=S^(p<<x)^(q<<y),v0=f[d^1][S][0],v1=f[d^1][S][1]; if(!v0&&!v1) continue; if(str[i][j]==‘x‘) { upd(f[d][T][0],v0),upd(f[d][T][1],v1); continue; } upd(f[d][T|(1<<x)|(1<<y)][0],v0),upd(f[d][T|(1<<x)|(1<<y)][1],v1); if(p||q) upd(f[d][T|(q<<x)|(p<<y)][0],v0),upd(f[d][T|(q<<x)|(p<<y)][1],v1); else upd(f[d][T][1],v0); } } d^=1,memset(f[d],0,sizeof(f[d])); for(S=0;S<=msk;S++) upd(f[d][(S<<1)&msk][0],f[d^1][S][0]),upd(f[d][(S<<1)&msk][1],f[d^1][S][1]); } for(S=0;S<=msk;S++) upd(ans,f[d][S][0]),upd(ans,f[d][S][1]); printf("%d",ans); return 0; }//1 4 ....
【CF845F】Guards In The Storehouse 插頭DP