1. 程式人生 > >Game HDU - 3657(最小割)

Game HDU - 3657(最小割)

Game

Time Limit: 4000/2000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others)
Total Submission(s): 1563    Accepted Submission(s): 664


Problem Description onmylove has invented a game on n × m grids. There is one positive integer on each grid. Now you can take the numbers from the grids to make your final score as high as possible. The way to get score is like
the following:
● At the beginning, the score is 0;
● If you take a number which equals to x, the score increase x;
● If there appears two neighboring empty grids after you taken the number, then the score should be decreased by 2(x&y). Here x and y are the values used to existed on these two grids. Please pay attention that "neighboring grids" means there exits and only exits one common border between these two grids.

Since onmylove thinks this problem is too easy, he adds one more rule:
● Before you start the game, you are given some positions and the numbers on these positions must be taken away.
Can you help onmylove to calculate: what's the highest score onmylove can get in the game?  

 

Input Multiple input cases. For each case, there are three integers n, m, k in a line.
n and m describing the size of the grids is n ×m. k means there are k positions of which you must take their numbers. Then following n lines, each contains m numbers, representing the numbers on the n×m grids.Then k lines follow. Each line contains two integers, representing the row and column of one position
and you must take the number on this position. Also, the rows and columns are counted start from 1.
Limits: 1 ≤ n, m ≤ 50, 0 ≤ k ≤ n × m, the integer in every gird is not more than 1000.  

 

Output For each test case, output the highest score on one line.  

 

Sample Input 2 2 1 2 2 2 2 1 1 2 2 1 2 7 4 1 1 1  

 

Sample Output 4 9 Hint As to the second case in Sample Input, onmylove gan get the highest score when calulating like this: 2 + 7 + 4 - 2 × (2&4) - 2 × (2&7) = 13 - 2 × 0 - 2 × 2 = 9.  

 

Author onmylove  

 

Source 2010 Asia Regional Chengdu Site —— Online Contest     解析:   棋盤問題的變形 多了點限制   遇到這種問題就向最小割去想    最小割就是求最小价值損失   對於預先選定的點 x   如果是白點 則 s 向 x 連一條INF的邊  如果是黑點 則 x 向 t 連一條INF的邊  因為權值為INF  所以無論怎樣 這條邊都不會成為割邊 所以就能代表這條邊已經被選擇   其它的就和棋盤問題一樣  只不過相鄰的點的邊權   加了限制之後 把這條邊的權值 由棋盤問題的INF 改為 2 * (w1 & w2)即可 跑一遍Dinic    然後sum - Dinic
#include <iostream>
#include <cstdio>
#include <sstream>
#include <cstring>
#include <map>
#include <cctype>
#include <set>
#include <vector>
#include <stack>
#include <queue>
#include <algorithm>
#include <cmath>
#include <bitset>
#define rap(i, a, n) for(int i=a; i<=n; i++)
#define rep(i, a, n) for(int i=a; i<n; i++)
#define lap(i, a, n) for(int i=n; i>=a; i--)
#define lep(i, a, n) for(int i=n; i>a; i--)
#define rd(a) scanf("%d", &a)
#define rlld(a) scanf("%lld", &a)
#define rc(a) scanf("%c", &a)
#define rs(a) scanf("%s", a)
#define rb(a) scanf("%lf", &a)
#define rf(a) scanf("%f", &a)
#define pd(a) printf("%d\n", a)
#define plld(a) printf("%lld\n", a)
#define pc(a) printf("%c\n", a)
#define ps(a) printf("%s\n", a)
#define MOD 2018
#define LL long long
#define ULL unsigned long long
#define Pair pair<int, int>
#define mem(a, b) memset(a, b, sizeof(a))
#define _  ios_base::sync_with_stdio(0),cin.tie(0)
//freopen("1.txt", "r", stdin);
using namespace std;
const int maxn = 1e5 + 10, INF = 0x7fffffff;
int dir[4][2] = {{0, 1}, {0, -1}, {1, 0}, {-1, 0}};
int n, m, k, s, t;
int way[55][55], vv[2550][2550];
int head[maxn], cur[maxn], vis[maxn], d[maxn], cnt, nex[maxn << 1];

struct node
{
    int u, v, c;
}Node[maxn << 1];

void add_(int u, int v, int c)
{
    Node[cnt].u = u;
    Node[cnt].v = v;
    Node[cnt].c = c;
    nex[cnt] = head[u];
    head[u] = cnt++;
}

void add(int u, int v, int c)
{
    add_(u, v, c);
    add_(v, u, 0);
}

bool bfs()
{
    queue<int> Q;
    mem(d, 0);
    Q.push(s);
    d[s] = 1;
    while(!Q.empty())
    {
        int u = Q.front(); Q.pop();
        for(int i = head[u]; i != -1; i = nex[i])
        {
            int v = Node[i].v;
            if(!d[v] && Node[i].c > 0)
            {
                d[v] = d[u] + 1;
                Q.push(v);
                if(v == t) return 1;
            }
        }
    }
    return d[t] != 0;
}

int dfs(int u, int cap)
{
    int ret = 0;
    if(u == t || cap == 0)
        return cap;
    for(int &i = cur[u]; i != -1; i = nex[i])
    {
        int v = Node[i].v;
        if(d[v] == d[u] + 1 && Node[i].c > 0)
        {
            int V = dfs(v, min(cap, Node[i].c));
            Node[i].c -= V;
            Node[i ^ 1].c += V;
            ret += V;
            cap -= V;
            if(cap == 0) break;
        }
    }
    if(cap > 0) d[u] = -1;
    return ret;
}

int Dinic()
{
    int ans = 0;
    while(bfs())
    {
        memcpy(cur, head, sizeof head);
        ans += dfs(s, INF);
    }
    return ans;
}

int main()
{
    while(scanf("%d%d%d", &n, &m, &k) != EOF)
    {
        int sum = 0;
        s = 0, t = n * m + 1;
        mem(head, -1), cnt = 0, mem(vv, 0);
        int w, x, y;
        rap(i, 1, n)
            rap(j, 1, m)
                rd(way[i][j]), sum += way[i][j];
        rap(i, 1, k)
        {
            rd(x), rd(y);
            if((x + y) & 1)
                add(s, (x - 1) * m + y, INF);
            else add((x - 1) * m + y, t, INF);
            vv[x][y] = 1;
        }
        rap(i, 1, n)
            rap(j, 1, m)
            {
                rep(k, 0, 4)
                {
                    int nx = i + dir[k][0];
                    int ny = j + dir[k][1];
                    if(nx < 1 || ny < 1 || nx > n || ny > m) continue;
                    if((i + j) & 1)
                        add((i - 1) * m + j, (nx - 1) * m + ny, 2 * (way[i][j] & way[nx][ny]));
                }
                if(vv[i][j]) continue;
                if((i + j) & 1) add(s, (i - 1) * m + j, way[i][j]);
                else add((i - 1) * m + j, t, way[i][j]);
            }
        cout << sum - Dinic() << endl;

    }



    return 0;
}

 

    

Game

Time Limit: 4000/2000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others)
Total Submission(s): 1563    Accepted Submission(s): 664


Problem Description onmylove has invented a game on n × m grids. There is one positive integer on each grid. Now you can take the numbers from the grids to make your final score as high as possible. The way to get score is like
the following:
● At the beginning, the score is 0;
● If you take a number which equals to x, the score increase x;
● If there appears two neighboring empty grids after you taken the number, then the score should be decreased by 2(x&y). Here x and y are the values used to existed on these two grids. Please pay attention that "neighboring grids" means there exits and only exits one common border between these two grids.

Since onmylove thinks this problem is too easy, he adds one more rule:
● Before you start the game, you are given some positions and the numbers on these positions must be taken away.
Can you help onmylove to calculate: what's the highest score onmylove can get in the game?  

 

Input Multiple input cases. For each case, there are three integers n, m, k in a line.
n and m describing the size of the grids is n ×m. k means there are k positions of which you must take their numbers. Then following n lines, each contains m numbers, representing the numbers on the n×m grids.Then k lines follow. Each line contains two integers, representing the row and column of one position
and you must take the number on this position. Also, the rows and columns are counted start from 1.
Limits: 1 ≤ n, m ≤ 50, 0 ≤ k ≤ n × m, the integer in every gird is not more than 1000.  

 

Output For each test case, output the highest score on one line.  

 

Sample Input 2 2 1 2 2 2 2 1 1 2 2 1 2 7 4 1 1 1  

 

Sample Output 4 9 Hint As to the second case in Sample Input, onmylove gan get the highest score when calulating like this: 2 + 7 + 4 - 2 × (2&4) - 2 × (2&7) = 13 - 2 × 0 - 2 × 2 = 9.  

 

Author onmylove  

 

Source 2010 Asia Regional Chengdu Site —— Online Contest