[关闭]
@ysner 2018-10-10T21:38:53.000000Z 字数 1762 阅读 1951

[SCOI2009]围豆豆

DP 状压DP


题面

戳我

解析

豆子数这么少,肯定状压啊。
于是设表示到了这个点,包围豆子情况为的方案数。
枚举一下出发点和最终豆子选取状态即可。
复杂度

嗯,得很美好,然后不会判断豆子是否被包围。。。。。。。
实际上,判断一个点在一个多边形内的标准,就是它朝一个方向走会与多边形的边相交奇数次。
因为每次跨越边界都是从多边形内(外)到多边形外(内)。
姑且钦定这个方向为正右。
然后自己把握一下线的位置就行(如豆子中心偏下,反正不能与边界重叠)。

  1. #include<iostream>
  2. #include<cstdio>
  3. #include<cmath>
  4. #include<cstdlib>
  5. #include<cstring>
  6. #include<algorithm>
  7. #include<queue>
  8. #define ll long long
  9. #define re register
  10. #define il inline
  11. #define fp(i,a,b) for(re int i=a;i<=b;++i)
  12. #define fq(i,a,b) for(re int i=a;i>=b;--i)
  13. using namespace std;
  14. const int N=12;
  15. 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];
  16. char s[N][N];
  17. bool vis[N][N][1<<10];
  18. struct dat{int x,y,S;};
  19. queue<dat>Q;
  20. il ll gi()
  21. {
  22. re ll x=0,t=1;
  23. re char ch=getchar();
  24. while(ch!='-'&&(ch<'0'||ch>'9')) ch=getchar();
  25. if(ch=='-') t=-1,ch=getchar();
  26. while(ch>='0'&&ch<='9') x=x*10+ch-48,ch=getchar();
  27. return x*t;
  28. }
  29. il int GetSS(re int x,re int y,re int xx,re int yy,re int S)
  30. {
  31. fp(i,0,d-1)
  32. if(((x==X[i]&&xx<X[i])||(x<X[i]&&xx==X[i]))&&y>Y[i]) S^=(1<<i);
  33. return S;
  34. }
  35. il void BFS(re int x,re int y)
  36. {
  37. memset(f,63,sizeof(f));f[x][y][0]=0;
  38. Q.push((dat){x,y,0});vis[x][y][0]=1;
  39. while(!Q.empty())
  40. {
  41. re int x=Q.front().x,y=Q.front().y,S=Q.front().S;Q.pop();
  42. fp(i,0,3)
  43. {
  44. re int xx=x+mx[i],yy=y+my[i];
  45. if(s[xx][yy]!='0') continue;
  46. re int SS=(i<2)?GetSS(x,y,xx,yy,S):S;
  47. if(f[xx][yy][SS]>f[x][y][S]+1)
  48. {
  49. f[xx][yy][SS]=f[x][y][S]+1;
  50. if(!vis[xx][yy][SS]) vis[xx][yy][SS]=1,Q.push((dat){xx,yy,SS});
  51. }
  52. }
  53. vis[x][y][S]=0;
  54. }
  55. fp(i,0,M)
  56. ans=max(ans,sum[i]-f[x][y][i]);
  57. }
  58. int main()
  59. {
  60. n=gi();m=gi();d=gi();M=(1<<d)-1;
  61. fp(i,0,d-1) w[i]=gi();
  62. memset(s,'#',sizeof(s));
  63. fp(i,1,n) scanf("%s",s[i]+1),s[i][m+1]='#';
  64. fp(i,1,n)
  65. fp(j,1,m)
  66. if(s[i][j]>='1'&&s[i][j]<='9') X[s[i][j]-'1']=i,Y[s[i][j]-'1']=j;
  67. fp(i,0,M)
  68. fp(j,0,d-1)
  69. if(i&(1<<j)) sum[i]+=w[j];
  70. fp(i,1,n) fp(j,1,m) if(s[i][j]=='0') BFS(i,j);
  71. printf("%d\n",ans);
  72. return 0;
  73. }
添加新批注
在作者公开此批注前,只有你和作者可见。
回复批注