Problem Solving report SOJ2835 Pick up Points

Description

Description recently Loy is very interested in playing a funny game. There is a board of N*m grid. Each grid has a point or not. If the adjacency grids both has one point, the someone can pick them up, and then these both grids has no point. The grids is adjacency only if the Manhattan distence between them is exactly 1. The purpose of the game is to gain as many points as possible. Input the first line was an Interger T, means the number of test cases. Each test case begins with a interger n,m (1 <= n,m <=), means the size of the board is n*m. Next n Line, each of the line have M intergers which is 1 or 0, means the grid has a point or not. Output output The maximum point Loy can get. Sample Input 1 0 1 1 (1 1) 1 sample Output60 Source LOY

The main topic: Test instructions is very simple, there is a n*m chess board, each lattice has 1 or 0 pieces, each operation can take away the adjacent two pieces (adjacent means two squares sharing an edge). Ask at most how many pieces can be taken away altogether.

Analysis: I feel very difficult, but have seen the number of questions than the other problems are higher ... Got drunk. This is the CFW model (cow grazing drink model, see another blog post poj 3281 Dining http://blog.csdn.net/maxichu/article/details/45190521), But it's hard to turn this problem into a cow grazing (I didn't think of it anyway).

As follows, the checkerboard is staggered, the i+j is the odd lattice as condition one (f in the CFW model), and the i+j is an even-numbered lattice for the condition two (d in the CFW model). The source point then connects one edge to the point of all conditions one, with a load of 1. The point of all condition two has an edge to the super sink, with a load of 1. The maximum flow of the super sinks represents the maximum number of pairs. Then be careful to traverse all points, if it is a point of condition one, then even one edge to the point around it (i.e. 4 conditions two points, if any). Note that if the condition is two points, you cannot have an edge around the perimeter, otherwise the traffic will be incorrectly shifted (see plot). Then run the maximum flow and multiply by 2.

Note that if 5<->2 is both bidirectional, then the maximum flow from 2 to 3, error!

on the code:

#include <iostream> #include <cstring> #include <algorithm> #include <queue> #include < cstdio> #include <sstream> #include <string> #include <cmath>using namespace Std;const int maxn = 20100;const int MAXM = 900000;const int INF = 0x3f3f3f3f;struct edge{int from, to, cap, next;}; Edge edge[maxm];int level[maxn];int map[150][150];int head[maxn];int src, des, cnt = 0;void Addedge (int from, int. to, INT CAP) {Edge[cnt].from = From;edge[cnt].to = To;edge[cnt].cap = Cap;edge[cnt].next = Head[from];head[from] = Cnt++;swap (fr OM, to); Edge[cnt].from = from;edge[cnt].to = To;edge[cnt].cap = 0;edge[cnt].next = Head[from];head[from] = cnt++;} int BFs () {memset (level,-1, sizeof level);queue<int> Q;while (!q.empty ()) Q.pop (); LEVEL[SRC] = 0;q.push (src); w Hile (!q.empty ()) {int u = q.front (); Q.pop (); for (int i = head[u]; I! = 1; i = edge[i].next) {int v = edge[i].to;if (edg E[I].CAP&&LEVEL[V] = =-1) {Level[v] = Level[u] + 1;q.push (v);}}} return leveL[des]! =-1;} int dfs (int u, int f) {if (U = = des) return f;int tem;for (int i = head[u]; I! =-1; i = edge[i].next) {int v = edge[i].to if (edge[i].cap&&level[v] = = Level[u] + 1) {tem = DFS (V, min (f, edge[i].cap)), if (Tem > 0) {edge[i].cap = t em;edge[i ^ 1].cap + = Tem;return tem;}} Level[u] = -1;return 0;} int dinic () {int ans = 0, Tem;while (BFS ()) {while (tem = DFS (SRC, INF)) {ans + = tem;}} return ans;} int main () {int Kase, M, n;cin >> kase;src = 0, des = 20005;while (kase--) {cin >> N>>m;memset (head,-1, sizeof head); cnt = 0;for (int i = 1; I <= n; i++) {for (int j = 1; j <= M; j + +) {cin >> map[i][j];if (map[i][j ] {if ((i + j)% 2 = = 1) addedge (SRC, (i-1) *100 + j, 1); Elseaddedge ((i-1) * + J, DES, 1);}} for (int i = 1, i <= N; i++) {for (int j = 1; j <= M; j + +) {if (!map[i][j]) continue;if (i+1<=n&&map[i+1][j ]) {Addedge ((i-1) * + J, I * + j, 1);} if (j + 1 <= m&&map[i][j+1]) {Addedge (i-1) *+ J, (i-1) * + + j + 1, 1);} if (i-1 >= 1 && map[i-1][j]) {Addedge ((i-1) * + j, (i-2) * + + J, 1);} if (j-1 >= 1 && map[i][j-1]) {Addedge ((i-1) * + + J, (i-1) * + j-1, 1);}}} cout << dinic () * 2 << Endl;} return 0;}

Well, that's it, it seems like we're going to keep practicing. Programming the beautiful want Azure clothes ah!!

Problem Solving report SOJ2835 Pick up Points