這道題初看也許會感覺無法下手,由於每次操作都是相鄰的兩個,所以可以考慮將棋盤黑白染色,這樣我們可以對黑色的格仔和白色的格仔單獨考慮。
設黑色格仔個數為cnt1,總和為sum1,白色格仔個數為cnt2,總和為sum2,最終所有格仔都變成了x,則很容易寫出下列的關係式:
cnt1 *x - sum1 = cnt2 * x - sum2
=> x * (cnt1 - cnt2) = sum1 - sum2
=> x = (sum1 - sum2)/ (cnt1 - cnt2)
現在討論cnt1 與 cnt2的情況:
1、若cnt1 = cnt2,則說明在sum1 = sum2的情況下,
若x可行,則x+1同樣可以,這樣我們可以通過二分的方法找出最小的滿足條件的x,求出最小步數;若sum1 != sum2則無解。
2、若cnt1!= cnt2,則我們解出了乙個x
這個x必須要滿足三個條件:
(1)x必須為整數
(2)x不小於所有格仔的最大值
(3)x必須要通過檢驗
如果x滿足這三個條件,則我們可以解出最小步數,否則無解。
那麼我們怎樣檢驗x是否可行呢,這個需要通過網路流來驗證。
設map[i][j]為格仔對應的數字,
對於每個黑色的格仔,從源點連一條邊,容量為x - map[i][j],並且對它周圍的四個白色格仔連一條邊容量為inf;對於每個白色格仔,向匯點連一條邊,容量為x - map[i][j]
設最大流為maxflow,若maxflow= (n * m * x - sum1 -sum2) >> 1的話,說明存在方案可以使所有數變成x,同時最小步數minstep = (n * m * x - sum1 - sum2) >> 1
注意到格仔的數可能很大,所以要使用longlong型別
這樣就解決了本題。
**:
#include#includeusing namespace std;
const int maxn = 50;
const int maxpoint = 3000;
const int maxm = 100000;
const long long inf = 0x3f3f3f3f3f3f3f3fll;
struct edge
e[maxm];
int map[maxn][maxn],head[maxpoint];
int dis[maxpoint],gap[maxpoint],cur[maxpoint],pre[maxpoint];
int t,n,m;
int ne,s,t,nodenum;
long long maxw,cnt1,sum1,cnt2,sum2,com;
void init()
inline int max(long long a,long long b)
inline void checkmin(long long &a,long long b)
inline long long gettime(long long x)
void insert(int u,int v,long long c)
long long sap()
aug = -1;
}goto loop;}}
int mind = nodenum;
for(int i = head[u];i != -1;i = e[i].next)
}if(--(gap[dis[u]]) == 0)break;
gap[dis[u] = mind + 1]++;
u = pre[u];
} return maxflow;
}bool check(long long x)
else insert((i - 1) * m + j,t,x - map[i][j]);
} }return ((sap() << 1) == (x * n * m - sum1 - sum2));
}void solve()
if(check(x))printf("%lld\n",gettime(x));
else printf("-1\n");
} }else
if(check(r))printf("%lld\n",gettime(r));
else printf("-1\n"); }}
void readdata()
} solve(); }}
int main()
poj 2112 最大流 二分法
安排c頭牛到某個擠奶器,使得每頭牛需要走的路程中最大路程的距離最小。先用floyd演算法,求出奶牛到每個擠奶器的最短距離,然後從最大的距離二分,當此距離可以使c頭牛,匹配成功,就讓右區間r mid 若不成功,就讓左區間l mid 之後繼續二分。每次二分後,都要重新建圖,另外加超級源點s和超級匯點t,...
二分法最大匹配
關鍵在於如何尋找增廣路徑 初始時最大匹配為空 for 二分圖左半邊的每個點i do 從點i出發尋找增廣路徑。如果找到,則把它取反 即增加了總了匹配數 如果二分圖的左半邊一共有n個點,那麼最多找n條增廣路徑。如果圖中共有m條邊,那麼每找一條增廣路徑 dfs或bfs 時最多把所有邊遍歷一遍,所花時間也就...
C 二分法查詢,遞迴二分法
用二分法來求需要查詢的值.includeusing namespace std 查詢key元素是否存在 int findkey const int buf 100 const int ilen,const int key else right left mid 1 查詢失敗 return 1 查詢k...