網路流 24題 方格取數

2022-08-14 05:00:10 字數 1812 閱讀 3970

方格取數問題

題目描述

在乙個有m*n個方格的棋盤中,每個方格中有乙個正整數。現要從方格中取數,使任意2個數所在方格沒有公共邊,且取出的數的總和最大。試設計乙個滿足要求的取數演算法。

輸入格式

檔案第1行有2個正整數m和n,分別表示棋盤的行數和列數。接下來的m行,每行有n個正整數,表示棋盤方格中的數。(0 <= m, n <= 30)

輸出格式

取數的最大總和.

輸入樣例

33 1 2 3 

3 2 3 

2 3 1

輸出樣例

11題目大意:

給出m*n的格仔,相鄰的格仔的值不可同時取,最後求出最大值。

我還誤以為只有兩種情況,用暴力不就好了嗎,不過wyy給我舉出其他情況,事實證明我想少了。

構圖:

如圖,我們會發現,黑色格仔都是可以同時選的,白色格仔也是同時可以走的。會發現同是黑色格仔(白色格仔),它們的行列座標加起來mod 2,都是一樣的。

所以,我們可以用二分圖來給它們歸類。首先,行列之和,為偶數的放在左邊,行列之和為奇數的放在右邊。於是,便得出,黑色格仔的放在右邊,白色格仔放在左邊。

因為黑白之間是互不可取的,以中間的黑色格仔為例,它不可達的格仔有它上下左右的白色格仔,於是把它們相連。同理,所有黑色格仔都這麼連。

並把黑色格仔(行列和為偶數)與s節點相連,白色格仔與t相連。

解題思想:

求出來的為最小割,也就是說,如果經過這個點,那就是把這個點割去了,不能選。而得出最小割,也就是得出了不選哪些格仔,所以,用總和減去最小割就是最後的答案。

細節:

我們一開始一直wrong,是因為陣列開小了,maxn直接開為35,可是在這乙個棋盤裡面,格仔數是遠遠不止這麼多的,要開到n^2。

**如下:

#include#include#includeusing namespace std;

const int maxn=1000,oo=10000000;//注意陣列大小,格仔數為n^2。

int ans;

int cur=-1,s,t,m,n;

int head[maxn],c[maxn][maxn],v[maxn],id[maxn][maxn],a[maxn][maxn];

int xx[5]=,yy[5]=;

struct space

edge[maxn*maxn];

void add(int from,int to,int va,int type)

void build(int x,int y)

}void init()

} s=0,t=n*m+1;

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

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

else

} } }

int dfs(int now,int mi)

} h=edge[h].next;

} return 0;

}//最小割(與最大流的**完全是一樣的)

int main()

cout<

這篇部落格寫得比較清楚。

網路流24題 方格取數

先對棋盤黑白染色 這是常見套路 我們發現,如果選了乙個黑點,那相鄰的白點就不能選,反之同理 出現了衝突關係,考慮最大權閉合子圖 把黑點看成正權點,白點看成負權點,黑點向相鄰白點連邊,跑最大權閉合子圖即可 include include include include define maxc 205 ...

網路流24題 方格取數

p2774 傳送門 方格取數和最大且要求兩兩沒有公共邊 遇到方格內的不相鄰問題,考慮黑白染色來對點分類 問題轉化為使黑點不和白點相鄰的最小代價,其中每個點的代價只計算一次 明顯的集合劃分模型,用最小割解決 include using namespace std define x first defi...

24題 方格取數問題 網路流

在乙個有 n m n times m n m 個方格的棋盤中,每個方格中有乙個正整數。現要從方格中取數,使任意 2 個數所在方格沒有公共邊,且取出的數的總和最大。這道題明顯是乙個二分圖。我們可以把每個點染色,將i j i ji j為偶數的點連向t tt,否則連向s ss。那麼對於每乙個連s ss的白...