@ysner
2018-10-10T13:38:53.000000Z
字数 1762
阅读 2509
DP 状压DP
豆子数这么少,肯定状压啊。
于是设表示到了这个点,包围豆子情况为的方案数。
枚举一下出发点和最终豆子选取状态即可。
复杂度。
嗯,得很美好,然后不会判断豆子是否被包围。。。。。。。
实际上,判断一个点在一个多边形内的标准,就是它朝一个方向走会与多边形的边相交奇数次。
因为每次跨越边界都是从多边形内(外)到多边形外(内)。
姑且钦定这个方向为正右。
然后自己把握一下线的位置就行(如豆子中心偏下,反正不能与边界重叠)。
#include<iostream>#include<cstdio>#include<cmath>#include<cstdlib>#include<cstring>#include<algorithm>#include<queue>#define ll long long#define re register#define il inline#define fp(i,a,b) for(re int i=a;i<=b;++i)#define fq(i,a,b) for(re int i=a;i>=b;--i)using namespace std;const int N=12;int n,m,d,w[N],f[N][N][1<<10],ans,M,sum[1<<10],mx[4]={1,-1,0,0},my[4]={0,0,1,-1},X[N],Y[N];char s[N][N];bool vis[N][N][1<<10];struct dat{int x,y,S;};queue<dat>Q;il ll gi(){re ll x=0,t=1;re char ch=getchar();while(ch!='-'&&(ch<'0'||ch>'9')) ch=getchar();if(ch=='-') t=-1,ch=getchar();while(ch>='0'&&ch<='9') x=x*10+ch-48,ch=getchar();return x*t;}il int GetSS(re int x,re int y,re int xx,re int yy,re int S){fp(i,0,d-1)if(((x==X[i]&&xx<X[i])||(x<X[i]&&xx==X[i]))&&y>Y[i]) S^=(1<<i);return S;}il void BFS(re int x,re int y){memset(f,63,sizeof(f));f[x][y][0]=0;Q.push((dat){x,y,0});vis[x][y][0]=1;while(!Q.empty()){re int x=Q.front().x,y=Q.front().y,S=Q.front().S;Q.pop();fp(i,0,3){re int xx=x+mx[i],yy=y+my[i];if(s[xx][yy]!='0') continue;re int SS=(i<2)?GetSS(x,y,xx,yy,S):S;if(f[xx][yy][SS]>f[x][y][S]+1){f[xx][yy][SS]=f[x][y][S]+1;if(!vis[xx][yy][SS]) vis[xx][yy][SS]=1,Q.push((dat){xx,yy,SS});}}vis[x][y][S]=0;}fp(i,0,M)ans=max(ans,sum[i]-f[x][y][i]);}int main(){n=gi();m=gi();d=gi();M=(1<<d)-1;fp(i,0,d-1) w[i]=gi();memset(s,'#',sizeof(s));fp(i,1,n) scanf("%s",s[i]+1),s[i][m+1]='#';fp(i,1,n)fp(j,1,m)if(s[i][j]>='1'&&s[i][j]<='9') X[s[i][j]-'1']=i,Y[s[i][j]-'1']=j;fp(i,0,M)fp(j,0,d-1)if(i&(1<<j)) sum[i]+=w[j];fp(i,1,n) fp(j,1,m) if(s[i][j]=='0') BFS(i,j);printf("%d\n",ans);return 0;}
