魔術球問題(網路流24題)

2022-02-27 09:43:42 字數 1397 閱讀 2115

假設有n根柱子,現要按下述規則在這n根柱子中依次放入編號為1,2,3,...的球。

(1)每次只能在某根柱子的最上面放球。

(2)在同一根柱子中,任何2個相鄰球的編號之和為完全平方數。

試設計乙個演算法,計算出在n根柱子上最多能放多少個球。例如,在4 根柱子上最多可放11 個球。

對於給定的n,計算在n根柱子上最多能放多少個球。

輸入輸出格式

輸入格式:

第1 行有1個正整數n,表示柱子數。

輸出格式:

程式執行結束時,將n 根柱子上最多能放的球數以及相應的放置方案輸出。檔案的第一行是球數。接下來的n行,每行是一根柱子上的球的編號。

輸入輸出樣例

輸入樣例#1:

4輸出樣例#1:

111 8

2 7 9

3 6 10

4 5 11

說明4<=n<=55

題意應該很好懂:給出n根柱子,在柱子上放球的條件是柱子為空或者上乙個放在這根柱子上的球的編號與這個球的編號相加是完全平方數。 最多能放多少球我們並不知道,但是有這樣乙個貪心策略是肯定沒問題的:如果能放在一顆球上面結果一定不會比另外用一根柱子重新放這顆球得到的結果要差。

所以我們考慮乙個球乙個球的往上加球。然後在建邊的時候可以考慮拆點來統計答案。

然後需要注意的就是拆點的時候注意一下編號不要和其他點重疊,記錄放球方案的時候可以直接在最大流增廣的時候記錄.

#include#define ll(x) ((x)<<1)

#define rr(x) ((x)<<1|1)

using namespace std;

const int inf=2147483647;

const int n=100000+5;

int n, s, t;

int cnt = 1;

int now = 0;

int ball = 0;

bool vis[n];

int last[n], head[n];

int nex[n], lev[n];

int st[n];

struct edgee[1000000+5];

void add(int x,int y,int z)

bool bfs()

}return lev[t] != -1;

}int dfs(int x,int flow)}}

return rest;

}int maxflow()

int main()

printf("%d\n",--ball);

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

printf("\n");

}return 0;

}

網路流24題 魔術球問題

列舉答案轉化為判定性問題,然後最小路徑覆蓋,可以轉化成二分圖最大匹配,從而用最大流解決。列舉答案a,在圖中建立節點1.a。如果對於i具體方法可以順序列舉a的值,當最小路徑覆蓋數剛好大於n時終止,a 1就是最優解。由於是順序放球,每根柱子上的球滿足這樣的特徵,即下面的球編號小於上面球的編號。抽象成圖論...

網路流24題 魔術球問題

以珠子為點,滿足條件就兩兩連邊 那麼就是讓你求n條路徑最多能覆蓋多少節點。眾所周知,最小邊覆蓋 點總數 最大匹配 不會看這裡link 於是拆點跑二分圖即可 大概就是s向x連邊 滿足條件的點k向x 連邊 x 向t連邊 有兩種方式 1.我們輪流加點,每次在殘量網路跑最大流就可以了 2.我們二分答案,每次...

網路流24題 魔術球問題

題目描述 將所有球看做點,在每根柱子上放球就是下邊的點向上邊的點連邊,可以連邊的條件是兩球編號之和為完全平方數。再把這n跟柱子看做是n條路徑,問題也就轉換成了用n條路徑覆蓋所有的點,也就是最小路徑覆蓋問題。最小路徑覆蓋數隨著點數的增加不會遞減,滿足二分的性質,但是二分時要重新構圖,所以不如直接順序列...