1. 程式人生 > >bzoj1294 [SCOI2009]圍豆豆

bzoj1294 [SCOI2009]圍豆豆

names 分享 amp col bits all 情況 int !=

Description

技術分享

Input

第一行兩個整數N和M,為矩陣的邊長。 第二行一個整數D,為豆子的總個數。 第三行包含D個整數V1到VD,分別為每顆豆子的分值。 接著N行有一個N×M的字符矩陣來描述遊戲矩陣狀態,0表示空格,#表示障礙物。而數字1到9分別表示對應編號的豆子。

Output

僅包含一個整數,為最高可能獲得的分值。

Sample Input

3 8
3
30 -100 30
00000000
010203#0
00000000

Sample Output

38

HINT

50%的數據滿足1≤D≤3。
100%的數據滿足1≤D≤9,1≤N, M≤10,-10000≤Vi≤10000。

正解:計算幾何+狀壓$dp$+$spfa$。

這題的難點就在於如何判斷一個豆子是否在多邊形內。

實際上有一個很好判斷的方法,那就是可以引一條水平線,看和多邊形有幾個交點,有奇數個交點就在多邊形內,否則在多邊形外。

但是還有一個情況。就是如果路徑從上往下,突然往水平拐,再往下拐,那麽這是有偶數個交點的,但是豆子還是在多邊形內。

不過我們可以把所有邊當成上開下閉的邊,只有當水平線與一條邊的下端點相交才算進去。

然後我們可以直接寫一個狀壓+$spfa$。

 1 #include <bits/stdc++.h>
 2 #define il inline
 3
#define RG register 4 #define ll long long 5 #define inf (1<<29) 6 7 using namespace std; 8 9 struct data{ int x,y,bin; }p[15]; 10 11 const int d1[4]={0,0,-1,1}; 12 const int d2[4]={-1,1,0,0}; 13 14 int f[15][15][1<<12],vis[15][15][1<<12],g[15][15],val[15],S,n,m,all,ans;
15 16 queue<data> Q; 17 18 il int gi(){ 19 RG int x=0,q=1; RG char ch=getchar(); 20 while ((ch<0 || ch>9) && ch!=-) ch=getchar(); 21 if (ch==-) q=-1,ch=getchar(); 22 while (ch>=0 && ch<=9) x=x*10+ch-48,ch=getchar(); 23 return q*x; 24 } 25 26 il char gc(){ 27 RG char ch=getchar(); 28 while ((ch<0 || ch>9) && ch!=#) ch=getchar(); 29 return ch; 30 } 31 32 il void spfa(RG int sx,RG int sy){ 33 for (RG int i=1;i<=n;++i) 34 for (RG int j=1;j<=m;++j) 35 for (RG int k=0;k<all;++k) f[i][j][k]=-inf; 36 Q.push((data){sx,sy,0}),f[sx][sy][0]=0,vis[sx][sy][0]=1; 37 while (!Q.empty()){ 38 RG data now=Q.front(); Q.pop(); 39 if (now.x==sx && now.y==sy) 40 ans=max(ans,f[now.x][now.y][now.bin]); 41 for (RG int k=0,x,y,yy,bin,del;k<4;++k){ 42 x=now.x+d1[k],y=now.y+d2[k]; 43 if (x<=0 || x>n || y<=0 || y>m || g[x][y]) continue; 44 bin=now.bin,yy=max(y,now.y),del=0; 45 if (k<=1){ 46 for (RG int i=1;i<=S;++i) 47 if (p[i].y==yy && p[i].x<x){ 48 bin^=1<<(i-1); 49 if (bin>>(i-1)&1) del+=val[i]; else del-=val[i]; 50 } 51 } 52 if (f[x][y][bin]<f[now.x][now.y][now.bin]+del-1){ 53 f[x][y][bin]=f[now.x][now.y][now.bin]+del-1; 54 if (!vis[x][y][bin]) vis[x][y][bin]=1,Q.push((data){x,y,bin}); 55 } 56 } 57 vis[now.x][now.y][now.bin]=0; 58 } 59 return; 60 } 61 62 int main(){ 63 #ifndef ONLINE_JUDGE 64 freopen("bean.in","r",stdin); 65 freopen("bean.out","w",stdout); 66 #endif 67 n=gi(),m=gi(),S=gi(),all=1<<S; 68 for (RG int i=1;i<=S;++i) val[i]=gi(); 69 for (RG int i=1;i<=n;++i) 70 for (RG int j=1;j<=m;++j){ 71 RG char ch=gc(); 72 if (ch==#) g[i][j]=-1; else g[i][j]=ch-0; 73 if (g[i][j]>=1 && g[i][j]<=9) p[g[i][j]]=(data){i,j}; 74 } 75 for (RG int i=1;i<=n;++i) 76 for (RG int j=1;j<=m;++j) if (!g[i][j]) spfa(i,j); 77 cout<<ans; return 0; 78 }

bzoj1294 [SCOI2009]圍豆豆