洛谷P4294 WC2008 遊覽計畫

2022-05-05 19:39:11 字數 1527 閱讀 5477

教練上次課講了插頭dp,然後列出的插頭dp題目裡有這道題。本來想練練插頭dp的結果用更快更簡單的斯坦納樹解決了這道題。

斯坦納樹經典題目。

斯坦納樹其實並不是很難,一般用來解決在一張無向圖上選

\(\text\)個點使這\(\text\)個點連通並且始所選邊邊權最小。

那麼回到本題。

設\(f_\)表示當前在第\(\text\)行\(\text\)列的點,狀態為\(\text\)的時候最小權值和。設\(\text\)代表\(\text\)的子集。

那麼轉移方程顯而易見。

\[f_ = min(f_,f_ - a_)

\]這個轉移應該不難看懂吧。

但是這裡會出現乙個問題:那就是會出現新的節點。

我們可以用最短路的方式求出下面乙個方程:

設\(\text\)為當前的節點,\(\text\)是新拓展出的與\(\text\)相連線的節點。

則:\[f_ = min(f_,f_ +a_)

\]然後我們就順利的解決了這道題。

#include const int maxn = 20;

const int maxm = 20;

const int inf = 0x3f3f3f3f;

typedef long long ll;

struct pair

pair(int _x,int _y)

};inline pair make_pair(int x,int y)

templateinline void read(t& res)

const int dir[4][2] = ,,,};

int n, m, i, j, k, tx, ty;

int a[maxn][maxn], f[maxn][maxn][1 << 11];

bool inq[maxn][maxn], ans[maxn][maxn];

struct state

state(int _x,int _y,int _s)

} las[maxn][maxn][1 << 11];

std::queueq;

inline void spfa(int s) }}}

void dfs(int i,int j,int s)

int main()

} for(int l = 1, liml = (1 << cnt) - 1;l <= liml;l++)

}if(f[i][j][l] != inf) q.push(make_pair(i,j)), inq[i][j] = 1;}}

spfa(l);

} printf("%d\n",f[tx][ty][(1 << cnt) - 1]);

dfs(tx,ty,(1 << cnt) - 1);

for(int i = 1;i <= n;i++)

ans[i][j] ? printf("o") : printf("_");

}puts("");

} return 0;

}

P4294 WC2008 遊覽計畫

題目鏈結 題目描述 從未來過紹興的小d有幸參加了winter camp 2008,他被這座歷史名城的秀麗風景所吸引,強烈要求遊覽紹興及其周邊的所有景點。主辦者將紹興劃分為 n nn 行 m mm 列 n m n m n m 個分塊,如下圖 8 景點含於方塊內,且乙個在這裡插入描述 方塊至多有乙個景點...

P4294 WC2008 遊覽計畫 斯坦納樹

題目鏈結 差不多是斯坦納樹裸題,不過邊權化成了點權,這樣在合併兩棵子樹時需要去掉根結點的權值,防止重複。題目還要求輸出解,只要在轉移時記錄下路徑,然後dfs一遍就好了。1 include2 using namespace std 3 typedef long long ll 4 const int ...

洛谷 P1685 遊覽

手玩樣例,我們很快 從題目後的提示 找到了 1 3 1 3 1 3,1 2 31 2 3 1 2 3,1 2 31 2 3 1 2 3 兩者不同 一共三條路徑。求出其權值之和再加上乘船返回兩次所需的時間,和樣例恰好一致。於是我們便可以把這個問題分成兩個子問題逐個求解 選擇從起點開始dfs,我們需要考...