hrbust1697 国际象棋

本文探讨了如何使用图论方法解决国际象棋中骑士控制最少格子数量的问题,通过构建图并应用DFS搜索算法,实现每个格子被骑士控制的最小化目标。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

二分图匹配 hrbust 1697 国际象棋
一个骑士控制两个格子 最少的骑士控制棋盘上的每一个格子。
#include<iostream>
#include<cstring>
#include<cstdio>
using namespace std;
#define clr(x) memset(x,0,sizeof(x))
struct node
{
int to,next;
}q[300000];
int head[40*10+100];
int tot;
void add(int s,int u)
{
    q[tot].to=u;
    q[tot].next=head[s];
    head[s]=tot++;
}
int l[10000];
int v[10000];
int find(int x)
{
    int k,i;
    for(i=head[x];i;i=q[i].next)
    {
        k=q[i].to;
        if(!v[k])
        {
            v[k]=1;
            if(l[k]==0||find(l[k]))
            {
                l[k]=x;
                return 1;
            }
        }
    }
    return 0;
}
int g[50][50];
int num[50][50];
long long sum;
int main()
{
    int f,n,m,i,j,p,pp;
    while( scanf("%d",&n)!=EOF)
    {
        clr(head);
        clr(g);
        clr(num);
        clr(l);
        tot=1;
        sum=0;
        int k=0;
        while(scanf("%d%d",&p,&pp))
        {
            if(pp==0&&p==0)break;
            p--;pp--;
            g[p][pp]=1;
            k++;
        }
        int number=0;
        for(i=0;i<n;i++)
        for(j=0;j<n;j++)
        {
            if(!g[i][j])num[i][j]=number++;
        }
        for(i=0;i<n;i++)
        for(j=0;j<n;j++)
            if(g[i][j]==0)
            {
                if(i+1<n&&j+2<n&&g[i+1][j+2]==0)add(num[i][j],num[i+1][j+2]);
                if(j+1<n&&i+2<n&&g[i+2][j+1]==0)add(num[i][j],num[i+2][j+1]);
                if(i+1<n&&j-2>=0&&g[i+1][j-2]==0)add(num[i][j],num[i+1][j-2]);
                if(i+2<n&&j-1>=0&&g[i+2][j-1]==0)add(num[i][j],num[i+2][j-1]);
                if(i-1>=0&&j+2<n&&g[i-1][j+2]==0)add(num[i][j],num[i-1][j+2]);
                if(i-2>=0&&j+1<n&&g[i-2][j+1]==0)add(num[i][j],num[i-2][j+1]);
                if(i-1>=0&&j-2>=0&&g[i-1][j-2]==0)add(num[i][j],num[i-1][j-2]);
                if(i-2>=0&&j-1>=0&&g[i-2][j-1]==0)add(num[i][j],num[i-2][j-1]);
            }
        n=n*n-k;
        for(i=0;i<n;i++)
        {
            clr(v);
            if(find(i))sum++;
        }
        printf("%lld\n",n-sum/2);
    }
    return 0;
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值