长脖子鹿放置
有些东西呢比较玄学,其中水太深你把握不住。
这道题首先有个小小的创新,即平常的染色方法无法把它变成二分图,从题目中的图片来看,长颈鹿从白色方格跳跃到了白色方格,二分图二分了个寂寞。这很好解决,小学奥数都学过对图各种各样的染色,对于这道题隔列染色就能解决问题。然后二分图交了一发40分。感谢评论区的大哥让我知道障碍重复的问题,但还是T了两个点。然后题解区第一篇给了灵感,只需要调换一下加边顺序,把可能匹配到新点的边尽量后加,这样一来find的时候就可以先看到这条边,就避免了打扰别人的过程,从而极大地(10倍)提升程序效率。也可以写网络流,但既然二分图匹配可以过那就懒得写网络流了。
#include<bits/stdc++.h>
//#define feyn
const int N=210;
using namespace std;
inline void read(int &wh){
wh=0;int f=1;char w=getchar();
while(w<'0'||w>'9'){if(w=='-')f=-1;w=getchar();}
while(w>='0'&&w<='9'){wh=wh*10+w-'0';w=getchar();}
wh*=f;return;
}
int m,n,num,a[N][N],cnt,sum;
bool d[N][N];
int f[8][2]={{-1,-3},{-3,-1},{-1,3},{3,-1},{-3,1},{1,3},{3,1},{1,-3}};
inline bool check(int x,int y){
return x<1||y<1||x>m||y>n||d[x][y];
}
struct edge{
int t,next;
}e[N*N*10];
int head[N*N],esum;
inline void add(int fr,int to){
e[++esum]=(edge){to,head[fr]};head[fr]=esum;
}
int c[N*N],t[N*N],nt=1;
inline bool find(int wh){
for(int i=head[wh],th;i;i=e[i].next){
if(t[th=e[i].t]==nt)continue;t[th]=nt;
if(c[th]==0||find(c[th]))return c[th]=wh,true;
}
return false;
}
signed main(){
#ifdef feyn
freopen("in.txt","r",stdin);
#endif
read(m);read(n);
for(int i=1;i<=m;i++){
for(int j=1;j<=n;j++)a[i][j]=++cnt;
}
read(num);int s1,s2;
for(int i=1;i<=num;i++){
read(s1);read(s2);
if(d[s1][s2]==false)sum++;
d[s1][s2]=true;
}
for(int i=1;i<=m;i+=2){
for(int j=1;j<=n;j++){
if(d[i][j])continue;
for(int k=0;k<8;k++){
int x=i+f[k][0],y=j+f[k][1];
if(check(x,y))continue;
add(a[i][j],a[x][y]);
}
}
}
int ans=0;
for(int i=1;i<=cnt;i++,nt++)ans+=find(i);
printf("%d",n*m-sum-ans);
return 0;
}
一如既往,万事胜意