題目描述
題解:這道題是斯坦納樹的典型例題。
首先看一眼資料範圍發現$10$的範圍不狀壓對不起出題人,然後考慮轉移。
設$f[i][j][s]$表示當前在點$(i,j)$,覆蓋特殊節點狀態為$s$的最小花費。
轉移有:
1.$s$不變,此時有$f[i][j][s]=min(f[i'][j'][s]+a[i'][j'])$;
2.$(i,j)$不變,此時有$f[i][j][s]=min(f[i][j][t]+f[i][j][s$^$t])$,其中$t$是$s$的子集。
轉移1是最短路形式,我們可用spfa轉移;
轉移2直接列舉子集。
**:
#include#include#include
#include
using
namespace
std;
#define n 15
intn,m;
int f[n][n][1
<<10
],mp[n][n];
intcnt;
struct
pair
pair(
int x,int
y):x(x),y(y){}
}p[n];
struct
three
three(
int x,int y,int
s):x(x),y(y),s(s){}
}fa[n][n][
1<<10
];int dx[4]=;
int dy[4]=;
bool
vis[n][n];
queue
q;bool check(int x,int
y)void spfa(int
s) }
}vis[x][y] = 0
; }
}bool
ot[n][n];
void dfs(int x,int y,int
s)else
}int
main()}}
for(int s = 1;s<(1
<)
for(int i=1;i<=n;i++)
for(int j=1;j<=m;j++)
if(f[i][j][s]<0x3f3f3f3f)q.push(pair(i,j)),vis[i][j]=1
; }
printf(
"%d\n
",f[p[0].x][p[0].y][(1
<1
]); dfs(p[
0].x,p[0].y,(1
<1
);
for(int i=1;i<=n;i++)
puts(
"");
}return0;
}
BZOJ 2595 Wc2008 遊覽計畫
啊 斯坦納樹 好像很厲害啊 反正我之前不會。其實不知道實用性怎麼樣 畢竟複雜度不小。大概過程就是乙個狀壓dp spfa 列舉狀態 從小狀態更新大狀態 再對當前狀態做一次像spfa一樣的鬆弛操作 下面這個人講的不錯 可以去看看 為什麼我的 又那麼短 有點擔心優美度了 有誰提一下建議嗎2333 我覺得還...
BZOJ 2595 Wc2008 遊覽計畫
n m 的網格,如果 a 0 則表示景點,否則表示這裡的需要的志願者人數。求一種安排志願者的方案使得所有景點連通且志願者最少。本題可以插頭dp,然而有乙個東西叫斯坦納樹,來學習學習。令 f i,j,s 表示 i,j 為根,連通性為 s 的最少志願者。則有轉移 f i,j,s min begin f ...
bzoj2595 Wc2008 遊覽計畫
斯坦納樹 f i zt 表示以i為根,連成的聯通塊包括那些景點 兩個轉移 f i zt f i tzt f i zt tzt a i f i zt f j zt a i i,j 相鄰 後面這個可以用spfa優化 記得先進行前乙個轉移,還有容斥減掉a i include include include...