欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

棋盘游戏

程序员文章站 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;
}
相关标签: 匈牙利算法模板