您的位置:首页 > 其它

[bzoj-3175][Tjoi2013]攻击装置 题解

2017-09-04 19:26 295 查看
题目传送门

题意解析:题目就是给了你一张n*n的图,在图上有的点可以放棋子,有的不可以,这里的棋子跟马一样走“日”,然后问你最多能放几个互不攻击的马。

My opinion:看到这种不能互相攻击的题,暴力点可以用dfs,但是这里n<=200,所以当然是用dfs二分图匹配了,建图十分明显,只要按与一个点能攻击到的所有点连一条边,然后跑二分图匹配就行了。最后的匹配数就是不可以放棋子的点数。但是这里有一个问题,因为你并不能(也许有dalao做到了,但是我这种蒟蒻不行)把点分成两边,所以最后的匹配点对会是正确的两倍。

总结:

1、输入后建图。

2、跑二分图匹配。

3、输出总的0的点数减去ans/2(ans是二分图跑出来的答案)。

跑得贼慢的代码:

#include
4000
<iostream>
#include<cmath>
#include<cstdio>
#include<cstring>
#include<algorithm>
#define rep(i,a,n) for (int i=a;i<=n;i++)
#define per(i,a,n) for (int i=a;i>=n;i--)
#define Clear(a,x) memset(a,x,sizeof(a))
#define ll long long
#define INF 2000000000
#define eps 1e-8
using namespace std;
ll read(){
ll x=0,f=1;
char ch=getchar();
while (ch<'0'||ch>'9') f=ch=='-'?-1:f,ch=getchar();
while (ch>='0'&&ch<='9') x=x*10+ch-'0',ch=getchar();
return x*f;
}
const int maxn=205,maxm=40005;;
const int dx[8]={-1,-2,-2,-1,1,2,2,1},
dy[8]={-2,-1,1,2,2,1,-1,-2};
char map[maxn][maxn];
int match[maxm];
int head[maxm],vet[maxm<<4],Next[maxm<<4];
bool flag[maxm];
int len,n,sum;
int calc(int x,int y){
return (x-1)*n+y;
}
void add(int u,int v){
vet[++len]=v;
Next[len]=head[u];
head[u]=len;
}
bool dfs(int u){
for (int e=head[u];e;e=Next[e]){
int v=vet[e];
if (flag[v]) continue;
int t=match[v];
match[v]=u;
flag[v]=1;
if (t==-1||dfs(t))
return true;
match[v]=t;
}
return false;
}
int main(){
n=read();
rep(i,1,n)
scanf("%s",map[i]+1);
rep(i,1,n)
rep(j,1,n)
if (map[i][j]=='0')
rep(k,0,7){
int x=i+dx[k],y=j+dy[k];
if (x<1||x>n||y<1||y>n||map[x][y]=='1') continue;
add(calc(i,j),calc(x,y));
}
Clear(match,-1);
int ans=0;
rep(i,1,n)
rep(j,1,n)
if (map[i][j]=='0'){
sum++;
Clear(flag,0);
flag[calc(i,j)]=1;
ans+=dfs(calc(i,j));
}
printf("%d\n",sum-ans/2);
return 0;
}


附上AC记录:

内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: