題面太鬼畜不粘了。
題意就是給一張n*m的網格圖,每個點有點權,有k個關鍵點,讓你把這k個關鍵點連成乙個聯通快的最小代價。
題解
這題nmk都非常小,解法肯定是狀壓,比較一般的解法插頭dp,但不太好寫。
但其實這道題是裸的斯坦納樹模型。
斯坦納樹是最小生成樹的變形,在一般情況下是np問題,但在k規模較少時可以用狀壓dp求解。
我們可以設dp[i][j][s]表示以(i,j)為根,覆蓋關鍵點集合為s時的最小代價。
對於這個狀態內部的更新,我們可以對s列舉子集,相當於把聯通塊拆成兩部分再合併起來,dp[i][j][s] <= dp[i][j][s]+dp[i][j][s^s]。其中s是子集。
對於這個狀態對外的更新,我們可以對和根有連邊的點轉移,dp[i'][j'][s']=dp[i][j][s]+a[i][j]。其實令s=s『也可以,反正到了s『時也得更新。
這種dp方法的好處就是只保留了乙個轉移點,降掉了我們列舉轉移點的複雜度。
**
#include#includeview code#include
#include
#include
#define mm make_pair
#define n 11
using
namespace
std;
queue
int,int> >q;
int ans,dp[n][n][1
<<10
],n,m,a[n][n],tot;
bool
tag[n][n];
const
int dx[4]=;
const
int dy[4]=;
struct
nodepre[n][n][
1<<10
];inline
void spfa(int x,int y,int
s); q.push(mm(vx,vy));}}
}}inline
void findans(int x,int y,int
s)int
main()
int ma=(1
<1
;
for(int s=0;s<=ma;++s);
}spfa(i,j,s);}}
int ans=2e9,prx,pry;
for(int i=1;i<=n;++i)for(int j=1;j<=m;++j)
if(dp[i][j][ma]
findans(prx,pry,ma);
cout
for(int i=1;i<=n;++i)
puts(
"");
}return0;
}
Wc2008 遊覽計畫 斯坦納樹
斯坦納樹的問題模型是 有乙個圖,要求保留圖中最少的邊 最小的邊權和使得某k個點相互連通。最小生成樹是斯坦納樹的一種特殊情況。我們用f i j s 表示方格中i,j位置與各個景點之間的聯通情況。如果景點數為3時,111表示全部聯通,101表示第二個景點沒有聯通。當然第x個景點的 f i j 1 狀態怎...
WC2008遊覽計畫(BZOJ2595)
傳送門 time limit 10 sec memory limit 256 mbsec special judge submit status 第一行有兩個整數,n和 m,描述方塊的數目。接下來 n行,每行有 m 個非負整數,如果該整數為 0,則該方塊為乙個景點 否則表示控制該方塊至少需要的志願者...
2595 Wc2008 遊覽計畫
time limit 10 sec memory limit 256 mbsec special judge submit 1312 solved 602 submit status discuss 第一行有兩個整數,n和 m,描述方塊的數目。接下來 n行,每行有 m 個非負整數,如果該整數為 0,...