網路流 魔術球問題

2022-05-05 16:15:10 字數 1849 閱讀 9111

題目鏈結

題目描述

«問題描述:

假設有\(n\)

\((4\leq n \leq 55)\)根柱子,現要按下述規則在這\(n\)根柱子中依次放入編號為\(1,2,3,...\)的球。

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

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

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

«程式設計任務:

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

輸入輸出格式

輸入格式

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

輸出格式

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

輸入輸出樣例

輸入樣例

4
輸出樣例

11

1 82 7 9

3 6 10

4 5 11

第一眼沒思路,第二眼還是沒有。

沒思路想耍流氓二分。似乎可以,顯然柱子越多,放的球越多(至少不會更少),滿足單調性。那就二分答案判斷唄。

怎麼判斷呢?

鑑於這是一道網路流的題。。。

圖怎麼建?什麼情況下,兩個點之間能有連邊?滿足兩點標號之和為完全平方數。數範圍不大,可以\(n^2\)列舉。但僅僅這樣似乎不行。因為操作物件是點,不是邊,因此要將點拆開。拆開之後,一邊鏈結起點,拆出來的點鏈結終點。至於點與點之間,則是小的鏈結大的。邊權都是\(1\)。

然後就是最大流板子。找到答案之後,再處理每條邊上的點就好了。

#include #include #include #include #include #define inf 10000000

using namespace std;

long long read()

int n, s, t;

struct szh

//因為要建很多遍圖,所以要清空

}a[400000];

int cnt = 1, hd[10000];

inline void add(int u, int v, int w)

int q[10000], dis[10000];

queueq;

bool bfs()

return dis[t];

}int dfs(int u, int f)

return ans;

}int mf;

void dinic()

bool check(int x)

dinic();

return x - mf <= n;

}int nxt[10000];

bool use[10000];

int main()

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

check(ans);

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

for(int j = hd[i + ans], v; v = a[j].to, j; j = a[j].next)

} for(int i = 1; i <= ans; ++i)

printf("\n");

} return 0;

}

網路流24題 魔術球問題

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

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

假設有n根柱子,現要按下述規則在這n根柱子中依次放入編號為1,2,3,的球。1 每次只能在某根柱子的最上面放球。2 在同一根柱子中,任何2個相鄰球的編號之和為完全平方數。試設計乙個演算法,計算出在n根柱子上最多能放多少個球。例如,在4 根柱子上最多可放11 個球。對於給定的n,計算在n根柱子上最多能...

網路流24題 魔術球問題

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