江苏省省赛 方格覆盖 题解

给定一个 n×nn imes n 的矩形,其中从左上角开始,对角线上连续的 kk 个格子中有障碍物。你可以把若干 1×21 imes2 的小矩形放置到该大矩形中,要求是放置的两个小矩形不能占据相同的格子,且不能碰到障碍物。例如右图是 n=1,k=2n=1,k=2 的例子,我们放置了 6 个 的小矩形。
在这里插入图片描述
给定 n,kn,k,请你输出一个方案,使得放置的 1×21 imes2 小矩形尽可能多。可以证明, n=4,k=2n=4,k=2 时,至多只能放置 66 个小矩形。

这题本质上就是一个贪心

方法1:横着扫,然后竖着扫

#include <bits/stdc++.h>
using namespace std;
int a[55][55],s;
int main(){
    int n,k;
    cin>>n>>k;
    for(int i=1;i<=k;i++)a[i][i]=-1;//障碍的放置,从左上角开始
    for(int i=1;i<=n;i++)//逐行扫,查看是否能放横着的
    	for(int j=1;j<n;j++)
    		if(a[i][j]==0&&a[i][j+1]==0){//查看是否有地方放,如果有放
    			a[i][j]=++s;
    			a[i][j+1]=s;//标号
			}
	for(int j=1;j<=n;j++)//逐列扫,查看是否能放竖着的
		for(int i=1;i<n;i++)
			if(a[i][j]==0&&a[i+1][j]==0){//查看是否有地方放,如果有放
				a[i][j]=++s;
				a[i+1][j]=s;//标号
			}
	for(int i=1;i<=n;i++){
		for(int j=1;j<=n;j++)
			if(a[i][j]==-1)cout<<0<<" ";
			else cout<<a[i][j]<<" ";//随便用什么格式输出,不妨用一个空格输出
		cout<<endl;
	}
	return 0;
}
/*
至于这种简单的贪心的正确性
考试时,我没有想到如何证明它是对的
我们可以稍微感性的去想一想
如果有剩余的格子
你就要让剩余的格子放在一起,你可以去尝试一下,总是不能把剩余的格子放在一起
*/

方法2:螺旋扫

考试结束后,王星钱说他是用了螺旋扫的方法,这种方法很巧妙,显然易见它是对的,只是码量稍微的大了一点点

先做一遍螺旋矩阵

#include <bits/stdc++.h>
using namespace std;
int a[55][55],s,f,x,y;
int dx[4]={0,1,0,-1};
int dy[4]={1,0,-1,0};
int fx[4]={1,-1,-1,1};
int main(){
    int n;
    cin>>n;
    int bonder[4]={1,n,n,1};
	x=1,y=1;
	for(int i=1;i<=n*n;i++){//n*n个格子
		a[x][y]=i;
		if(x+dx[f]<bonder[0]||y+dy[f]>bonder[1]||x+dx[f]>bonder[2]||y+dy[f]<bonder[3])bonder[f]+=fx[f],f=(f+1)%4;//进行螺旋
		x+=dx[f],y+=dy[f];
	}
	for(int i=1;i<=n;i++){
		for(int j=1;j<=n;j++)
			cout<<a[i][j]<<" ";
		cout<<endl;
	}
	return 0;
}

确保对了之后开始进行赋值

#include <bits/stdc++.h>
using namespace std;
int a[55][55],s,f,x,y;
int dx[4]={0,1,0,-1};
int dy[4]={1,0,-1,0};
int fx[4]={1,-1,-1,1};
int main(){
    int n,k;
    cin>>n>>k;
    int bonder[4]={1,n,n,1};
    for(int i=1;i<=k;i++)a[i][i]=-1;//障碍的放置,从左上角开始
	x=1,y=1;//要这样写,否则会错k=0的点
	for(int i=1;i<=n*n;i++){//n*n个格子
		if(x+dx[f]<bonder[0]||y+dy[f]>bonder[1]||x+dx[f]>bonder[2]||y+dy[f]<bonder[3])bonder[f]+=fx[f],f=(f+1)%4;//进行螺旋
		if(a[x][y]==0&&a[x+dx[f]][y+dy[f]]==0){//赋值
			a[x][y]=++s;
			a[x+dx[f]][y+dy[f]]=s;
		}
		x+=dx[f],y+=dy[f];
	}
	for(int i=1;i<=n;i++){
		for(int j=1;j<=n;j++)
			if(a[i][j]==-1)cout<<0<<" ";
			else cout<<a[i][j]<<" ";//随便用什么格式输出,不妨用一个空格输出
		cout<<endl;
	}
	return 0;
}
原文地址:https://www.cnblogs.com/zhaohaikun/p/12816986.html