棋盘游戏
程序员文章站
2022-04-16 12:54:53
...
Sample Input
3 3 4
1 2
1 3
2 1
2 2
3 3 4
1 2
1 3
2 1
3 2
Sample Output
Board 1 have 0 important blanks for 2 chessmen.
Board 2 have 3 important blanks for 3 chessmen.
//题意:同行、同列中只能有一个棋子,给定一个地图,求该地图中能放的最大棋子数和重要点个数(介绍见思路)。
//思路:匈牙利算法模板题。直接套模板可求最大棋子数。把一个原本可以放棋子的地方(map[][]==1的点)设置成不能放棋子(map[][]==0),若最大棋子数变少了,那么该点为“重要点”。
#include <iostream>
#include <cstdio>
#include <cstring>
#include <string>
#include <cmath>
#include <cstdlib>
#include <algorithm>
using namespace std;
#define MAX 100+10
int n, m, k;
int x[MAX*MAX], y[MAX*MAX]; //存放可以放棋子的点的坐标
int map[MAX][MAX]; //地图
int used[MAX], visit[MAX];
int find(int x)
{
int i;
for (i = 1; i <= m; i++)
{
if (map[x][i] == 1 && visit[i] == 0)
{
visit[i] = 1;
if (used[i] == 0 || find(used[i]) == 1)
{
used[i] = x;
return 1;
}
}
}
return 0;
}
//匈牙利算法(递归实现)
int hungarian()
{
int i, sum = 0;
memset(used, 0, sizeof(used));
for (i = 1; i <= n; i++)
{
memset(visit, 0, sizeof(visit));
if (find(i))
sum++;
}
return sum;
}
int main()
{
int i, tt = 1;
while (~scanf("%d%d%d", &n, &m, &k))
{
memset(map, 0, sizeof(map));
for (i = 1; i <= k; i++)
{
scanf("%d%d", &x[i], &y[i]);
map[x[i]][y[i]] = 1;
}
int ans = hungarian(); //求棋子的最大个数
int sum = 0;
//若把一个原本是1的地方换成0后,最大棋子个数减小,则该点为重要点
for (i = 1; i <= k; i++)
{
map[x[i]][y[i]] = 0;
int num = hungarian();
if (num < ans)
sum++;
map[x[i]][y[i]] = 1;
}
printf("Board %d have %d important blanks for %d chessmen.\n", tt, sum, ans);
tt++;
}
return 0;
}
上一篇: ac图轮之匈牙利算法--月老的难题