【 HDU - 5093】Battle ships(匈牙利算法,二分图匹配)
題干:
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<T<12) at the beginning line, which means following T test cases.?
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題目大意:
給出一個n行m列的圖,*代表海域,o代表冰水,#代表冰山,要想在海域中放置船,保證船與船之間不能相互看到,之間只要有山就不能看到,問最多能放多少船。
(也就是冰水和冰山都不能放船,但是冰山就能隔開兩個船,冰水就不行)
將一片最多只能放一個船的連續網格叫做‘塊’。
以樣例一為例
首先只考慮行,將每個塊標號:將答案存入x [ ] [ ]
1000
0000
2203
0004
再此只考慮列,將每個塊標號:將答案存入y [ ][ ]
1000
0000
2304
0004
解題報告:
? ?建圖,注意那個line數組那些,不要開數組開小了,因為totx和toty都可能比較大。
其實是這個題的進化版本:【BZOJ - 1059】矩陣游戲(二分圖匹配,建圖,最小邊覆蓋)。
不同點在于,他那個題不需要縮點,就相當于你這個題中每一行和每一列就是自己一個連通塊,中間沒有東西把他們分割開來,也就是說如果沒有 ' # ' ,那么就退化成bzoj這個題了。
這題也是這樣,二分圖中的邊代表原圖中的每一個點(這里的點指的是連通塊的某一個交點),當選擇了某一條邊,也就說明連接的左右兩個點已經被占用了(代表對應的行連通塊和列連通塊被使用了)
思考方式和這個題也很像【HDU - 1281 】
AC代碼:
#include<cstdio> #include<iostream> #include<algorithm> #include<queue> #include<map> #include<vector> #include<set> #include<string> #include<cmath> #include<cstring> #define ll long long #define pb push_back #define pm make_pair using namespace std; char maze[555][555]; int visx[555][555],visy[555][555]; int n,m; int totx,toty; bool line[2500][2500]; int nxt[2505]; bool used[2555]; bool find(int x) {for(int i = 1; i<=toty; i++) {if(line[x][i] && used[i]==0) {used[i]=1;if(nxt[i] == -1 || find(nxt[i])) {nxt[i] = x;return 1;}}}return 0; } int match() {int sum = 0;memset(nxt,-1,sizeof nxt);for(int i = 1; i<=totx; i++) {memset(used,0,sizeof used);if(find(i)) sum++;}return sum; } int main() {int t;cin>>t;while(t--) {scanf("%d%d",&n,&m);memset(visx,0,sizeof visx);memset(visy,0,sizeof visy);memset(line,0,sizeof line);totx=toty=0;for(int i = 1; i<=n; i++) scanf("%s",maze[i]+1);for(int i = 1; i<=n; i++) {for(int j = 1; j<=m; j++) {if(maze[i][j] == '*' || maze[i][j] == 'o') {if(maze[i][j-1]=='#' || j == 1) visx[i][j] = ++totx;else visx[i][j] = visx[i][j-1];if(maze[i-1][j]=='#' || i == 1) visy[i][j] = ++toty;else visy[i][j] = visy[i-1][j];}}}for(int i = 1; i<=n; i++) {for(int j = 1; j<=m; j++) {if(maze[i][j] == '*') {line[visx[i][j]][visy[i][j]] = 1;}}}printf("%d\n",match());} return 0 ; }?
總結
以上是生活随笔為你收集整理的【 HDU - 5093】Battle ships(匈牙利算法,二分图匹配)的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: smartagt.exe - smart
- 下一篇: 中位数及带权中位数问题(转)