bzoj2595 Wc2008 遊覽計畫

2022-05-09 11:45:09 字數 1451 閱讀 2711

題目描述

題解:這道題是斯坦納樹的典型例題。

首先看一眼資料範圍發現$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...