程序師世界是廣大編程愛好者互助、分享、學習的平台,程序師世界有你更精彩!
首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫知識
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
 程式師世界 >> 編程語言 >> C語言 >> C++ >> C++入門知識 >> HDU 5093 Battle ships(二部圖最大匹配)

HDU 5093 Battle ships(二部圖最大匹配)

編輯:C++入門知識

HDU 5093 Battle ships(二部圖最大匹配)


Battle ships

Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 65536/65536 K (Java/Others)
Total Submission(s): 271 Accepted Submission(s): 128


Problem Description Dear contestant, now you are an excellent navy commander, who is responsible of a tough mission currently.

Your fleet unfortunately encountered an enemy fleet near the South Pole where the geographical conditions are negative for both sides. The floating ice and iceberg blocks battleships move which leads to this unexpected engagement highly dangerous, unpredictable and incontrollable.

But, fortunately, as an experienced navy commander, you are able to take opportunity to embattle the ships to maximize the utility of cannons on the battleships before the engagement.

The target is, arrange as many battleships as you can in the map. However, there are three rules so that you cannot do that arbitrary:

A battleship cannot lay on floating ice
A battleship cannot be placed on an iceberg

Two battleships cannot be arranged in the same row or column, unless one or more icebergs are in the middle of them.

Input There is only one integer T (0
For each test case, two integers m and n (1 <= m, n <= 50) are at the first line, represents the number of rows and columns of the battlefield map respectively. Following m lines contains n characters iteratively, each character belongs to one of ‘#’, ‘*’, ‘o’, that symbolize iceberg, ordinary sea and floating ice.
Output For each case, output just one line, contains a single integer which represents the maximal possible number of battleships can be arranged.
Sample Input
2
4 4
*ooo
o###
**#*
ooo*
4 4
#***
*#**
**#*
ooo#

Sample Output
3
5

Source 2014上海全國邀請賽——題目重現(感謝上海大學提供題目)

題目大意: 在海上(*)放戰艦,任意兩個戰艦不能出現在同一行或列,除非中間有冰山(#)相隔。問最多放多少戰艦。
解題思路: 比賽時沒有想到用二部圖來解。後來發現是白書二部圖的經典題型。 現將行和列,以冰山(#)為分隔,分割成多段。對於每一個可能放置的位置(*),將其所在的行和列的分段相連。表達的意思就是,這個點如果放置,那麼相鄰的同一區段(*、o)都不能再用,就是一個二部圖的思想。 \\
\
\

參考代碼:
#include 
#include 
#include 
#include 
using namespace std;

const int MAXN = 55*25;
char graph[MAXN][MAXN];
int nCase, m, n, idx, totalR, matching, pairRC[MAXN];
bool visitedC[MAXN];
vector reachedC[MAXN];

struct {
    int r, c;
} id[MAXN][MAXN];

void init() {
    idx = matching = 0;
    for (int i = 0; i < MAXN; i++) {
        reachedC[i].clear();
    }
    memset(pairRC, -1, sizeof(pairRC));
}

void input() {
    scanf("%d%d", &m, &n);
    for (int i = 0; i < m; i++) {
        scanf("%s", graph[i]);
    }
}

bool findPath(int r) {
    for (int i = 0; i < reachedC[r].size(); i++) {
        int c = reachedC[r][i];
        if (!visitedC[c]) {
            visitedC[c] = true;
            if (pairRC[c] == -1 || findPath(pairRC[c])) {
                pairRC[c] = r;
                return true;
            }
        }
    }
    return false;
}

void solve() {
    for (int i = 0; i < m; i++) {
        id[i][0].r = ++idx;
        for (int j = 1; j < n; j++) {
            if (graph[i][j] == '#' && graph[i][j] != graph[i][j-1]) {
                id[i][j].r = ++idx;
            } else {
                id[i][j].r = idx;
            }
        }
        if (graph[i][n-1] == '#') idx--;
    }
    totalR = idx;
    for (int j = 0; j < n; j++) {
        id[0][j].c = ++idx;
        for (int i = 1; i < m; i++) {
            if (graph[i][j] == '#' && graph[i][j] != graph[i-1][j]) {
                id[i][j].c = ++idx;
            } else {
                id[i][j].c = idx;
            }
        }
        if (graph[n-1][j] == '#') idx--;
    }

    for (int i = 0; i < m; i++) {
        for (int j = 0; j < n; j++) {
            if (graph[i][j] == '*') {
                reachedC[id[i][j].r].push_back(id[i][j].c);
            }
        }
    }
/*
    for (int i = 1; i <= totalR; i++) {
        printf("%d: ", i);
        for (int j = 0; j < reachedC[i].size(); j++) {
            printf("%d ", reachedC[i][j]);
        }
        printf("\n");
    }
*/
    for (int r = 1; r <= totalR; r++) {
        memset(visitedC, false, sizeof(visitedC));
        if (findPath(r)) {
            matching++;
        }
    }

    printf("%d\n", matching);
}

int main() {
    scanf("%d", &nCase);
    while (nCase--) {
        init();
        input();
        solve();
    }
    return 0;
}


  1. 上一頁:
  2. 下一頁:
Copyright © 程式師世界 All Rights Reserved