CQOI2017 小Q的棋盤

2022-03-29 21:27:31 字數 1215 閱讀 8594

給定一棵樹,點數為n,從根節點出發,每一步可以走向與當前點有直接邊相連的點,問走m步最多能經過多少個點。邊和點均可以重複經過,但不重複計數。

\(f[p][j]\) 表示從 \(p\) 出發走向以 \(p\) 為根的子樹,一共走 \(k\) 步並且最終回到 \(p\),最多能經過的點數。

\(g[p][j]\) 表示從 \(p\) 出發走向以 \(p\) 為根的子樹,一共走 \(k\) 步並且最終不回到 \(p\),最多能經過的點數。

考慮 \(f[p][j]\) 的轉移,走的情況應該是從 \(p\) 出發,走向某棵子樹,再走回 \(p\),再走向某棵子樹,再走回 \(p\),……,最後走回 \(p\)。

列舉 \(p\) 的所有子樹,對於當前的子樹 \(x\),考慮分配給其多少步 \(k\),由於還要走回 \(p\),故 \(k\) 的範圍即是 \([0,j-2]\),狀態轉移方程即為:

\[f[p][j]=\mathop_\

\]邊界:\(f[p][0]=1\)。

考慮 \(g[p][j]\) 的轉移,對於當前的子樹 \(x\),走的情況無非以下兩種:

對於第一種情況:

\[g[p][j]=\mathop_\

\]對於第二種情況:

\[g[p][j]=\mathop_\

\]邊界:\(g[p][0]=1\)。

最後的答案為 \(g[0][1 \ldots m]\) 中的最大值,因為如果不足 \(m\) 步就達到了最大值的話,剩下的步數可以隨便走。

#include #include #include #include using namespace std;

const int n=110;

struct edgeedge[n<<1];int idx;

int h[n];

void add_edge(int u,int v);h[u]=idx;}

int f[n][n];

int g[n][n];

int n,m;

void dfs(int p,int fa) }}

int main()

dfs(1,0);

int ans=0;

for(int i=1;i<=m;i++)ans=max(ans,g[1][i]);

printf("%d\n",ans);

return 0;

}

CQOI2017 小Q的棋盤

問題描述 小q正在設計一種棋類遊戲。在小q設計的遊戲中,棋子可以放在棋盤上的格點中。某些格點之間有連線,棋子只能 在有連線的格點之間移動。整個棋盤上共有v個格點,編號為0,1,2 v 1,它們是連通的,也就是說棋子從任意格 點出發,總能到達所有的格點。小q在設計棋盤時,還保證棋子從乙個格點移動到另外...

CQOI2017 小Q的棋盤

看到這道題,很容易想到是一道樹型dp,那麼該如何做?首先我們可以先這樣定義狀態,fi,jf fi,j 表示以i ii為根節點,向下走j jj步最多能經過多少點,但很明顯,只是這樣是不行的,所以我們再加一維,第三維為0表示不會到根節點,第三維為1表示需要回到根節點,那麼就可以得出狀態轉移方程 f ma...

CQOI2017 老C的方塊

傳送門 nkoj4042 這是一道網路流題。我在這道題上耗了很久 感謝 oblack幫我修改 這道題的思維上的難度並不大。以下是我的想法 首先要確定乙個大的方向,題目中要求移除一些方塊使得剩餘方塊無法構成 討厭的形狀 很容易就想到了最小割。仔細觀察一下,可以發現這些討厭的形狀是由兩個方格 一條特殊的...