• 江苏省省赛 方格覆盖 题解


    给定一个 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;
    }
    
  • 相关阅读:
    迭代器、生成器、装饰器(转)
    Python小数据池
    接阿里云oss有感
    VSCode快捷键
    前端跨域调请求 nginx反向代理
    Git生成密钥
    【westorm系列之二】配置格式化
    钉钉安卓端无法渲染数据
    express 写接口
    js正则匹配身份证号 有坑
  • 原文地址:https://www.cnblogs.com/zhaohaikun/p/12816986.html
Copyright © 2020-2023  润新知