網路流24題04 魔術球問題

2021-07-30 07:15:15 字數 1654 閱讀 7206

description

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

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

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

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

程式設計任務:

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

input format

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

output format

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

sample input

c++4

1 4

sample output

c++11

1 8

2 7 9

3 6 10

4 5 11

1 2

3 4

5 11

1 8

2 7 9

3 6 10

4 5 11

分析:一開始很容易想到直接對於兩個符合條件的編號連流量為1的邊,建超級源和超級匯。然後列舉答案,看是否符合條件,跑dinic就可以了,注意是每次用ans-=dfs(0,inf),ans表示用的柱子,明顯當你用的柱子數量》n時,就不能跑了。方案的話記錄一下反向邊就好。

#include

#include

#include

#include

#include

#define fo(i,a,b) for(int i=a;i<=b;i++)

#define fd(i,a,b) for(int i=a;i>=b;i--)

using namespace std;

const int n=1e5+5;

const int inf=2147483646;

int n,m;

typedef long long ll;

int dis[10001],cur[n],head[n],go[n],next[n],tot=1,t=10000;

bool mark[n];

int val[n],to[n];

intq[n],ans,s;

inline void add(int

x,int

y,int z)

inline void ins(int

x,int

y,int z)

inline bool bfs()}}

return dis[t]!=-1;

}inline int dfs(int

x,int f)

}if (!used)dis[x]=-1;

return used;

}inline void dinic()

}int main()

printf("%d\n",s-1);

//return

0; fo(i,1,s-1)}}

fo(i,1,s-1)

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.我們二分答案,每次...