CF720C Homework(构造)(暴力)

该博客探讨了一种结合暴力与构造思想的算法问题,主要涉及矩阵填充和计数。当n和m小于5时,采用深度优先搜索暴力解决;当n大于5且m小于5,或者反之,问题等价。对于特定情况,如n=3,m=5,给出了详细的处理逻辑。此外,还讨论了边界情况和特殊情况的处理。
摘要由CSDN通过智能技术生成

解析

本题的关键是暴力与构造结合的思想
本题一排排往上填的想法不难得出,但是在列数较小的时候就会GG
所以考虑在n>=5,m<5时,交换n,m,显然问题还是等价的
如果nm均小于5,就直接暴力dfs解决
在最后的边界需要打亿个小表
还有一个特殊情况需要特判
3100岂是浪得虚名

代码

#include<bits/stdc++.h>
using namespace std;
const int N=2e5+100;
const int mod=1e9+7;
#define ll long long
ll read(){
	ll x=0,f=1;char c=getchar();
	while(!isdigit(c)){if(c=='-')f=-1;c=getchar();};
	while(isdigit(c)){x=x*10+c-'0';c=getchar();};
	return x*f;
}
int n,m,k;
vector<int>s[N];
int a[16][16],flag;
void dfs(int x,int y){
	if(y>m){
		dfs(x+1,1);return;
	}
	if(x>n){
		int num(0);
		for(int i=1;i<n;i++){
			for(int j=1;j<m;j++){
				int cnt=a[i][j]+a[i+1][j]+a[i][j+1]+a[i+1][j+1];
				if(cnt==3) num++;
				if(cnt==4) num+=4;
			}
		}
		if(num==k){
			for(int i=1;i<=n;i++){
				for(int j=1;j<=m;j++) putchar(a[i][j]||(k==0&&i==1&&j==1)?'*':'.');
				putchar('\n');
			}
			flag=1;
		}
		return;
	}
	a[x][y]=0;dfs(x,y+1);if(flag) return;
	a[x][y]=1;dfs(x,y+1);
	a[x][y]=0;
}
void bf(){
	dfs(1,1);
	if(!flag) printf("-1\n");
	putchar('\n');
	return;
}
void work1(){
	int x=m-5;
	//printf("k=%d\n",k);
	if(m==5){
		if(k==0){
			flag=1;return;
		}
		if(k==1){
			s[n][1]=1;
			flag=1;return;
		}
		if(k==2){
			s[n][1]=s[n][5]=1;
			flag=1;return;
		}
		if(k==3){
			s[n][1]=s[n][3]=1;
			flag=1;return;
		}
		if(k==4){
			s[n][2]=s[n][4]=1;
			flag=1;return;
		}
		if(k==5){
			s[n][1]=s[n][2]=1;
			flag=1;return;
		}
		if(k==6){
			s[n][1]=s[n][2]=s[n][5]=1;
			flag=1;return;
		}
		if(k==7){
			s[n][1]=s[n][2]=s[n][4]=1;
			flag=1;return;
		}
		if(k==8){
			flag=0;return;
		}
		if(k==9){
			s[n][1]=s[n][2]=s[n][3]=1;
			flag=1;return;
		}
		if(k==10){
			s[n][1]=s[n][2]=s[n][4]=s[n][5]=1;
			flag=1;return;
		}
		if(k==11){
			flag=0;return;
		}
		if(k==12){
			flag=0;
			return;
		}
		if(k==13){
			s[n][1]=s[n][2]=s[n][3]=s[n][4]=1;
			flag=1;return;
		}
		if(k==14){
			flag=0;
			return;
		}
		if(k==15){
			flag=0;
			return;
		}
		if(k==16){
			s[n][1]=s[n][3]=s[n][4]=s[n][5]=s[n][2]=1;
			flag=1;return;
		}
		flag=0;return;
	}
	else{
		if(k==0){
			flag=1;return;
		}
		if(k==1){
			s[n][m]=1;
			flag=1;return;
		}
		if(k==2){
			s[n][x+2]=1;
			flag=1;return;
		}
		if(k==3){
			s[n][x+2]=s[n][m]=1;
			flag=1;return;
		}
		if(k==4){
			s[n][x+2]=s[n][x+4]=1;
			flag=1;return;
		}
		if(k==5){
			s[n][x+1]=s[n][m]=1;
			flag=1;return;
		}
		if(k==6){
			s[n][x+1]=s[n][x+4]=1;
			flag=1;return;
		}
		if(k==7){
			s[n][x+2]=s[n][x+4]=s[n][x+5]=1;
			flag=1;return;
		}
		if(k==8){
			s[n][x+1]=s[n][x+2]=1;
			flag=1;return;
		}
		if(k==9){
			s[n][x+1]=s[n][x+2]=s[n][m]=1;
			flag=1;return;
		}
		if(k==10){
			s[n][x+1]=s[n][x+2]=s[n][x+4]=1;
			flag=1;return;
		}
		if(k==11){
			flag=0;return;
		}
		if(k==12){
			s[n][x+1]=s[n][x+2]=s[n][x+3]=1;
			flag=1;return;
		}
		if(k==13){
			s[n][x+1]=s[n][x+2]=s[n][x+4]=s[n][x+5]=1;
			flag=1;return;
		}
		if(k==14){
			flag=0;return;
		}
		
		if(k==15){
			flag=0;return;
		}
		
		if(k==16){
			s[n][x+1]=s[n][x+2]=s[n][x+3]=s[n][x+4]=1;
			flag=1;return;
		}
		if(k==19){
			s[n][x+1]=s[n][x+2]=s[n][x+3]=s[n][x+4]=s[n][x+5]=1;
			flag=1;return;
		}
		flag=0;return;
	}
}
void work2(int x,int y){
	flag=1;
	if(k==0) return;
	y--;
	//printf("k=%d\n",k);
	if(k==1){
		if(y<=m-2) s[x][m]=1;
		else s[x+1][1]=1;
		return;
	}
	if(k==2){
		if(y<=m-3) s[x][m-1]=1;
		else s[x+1][2]=1;
		return;
	}
	if(k==3){
		if(y<=m-4){
			s[x][y+2]=1;s[x][m]=1;
		}
		else if(y>=m-1){
			s[x+1][1]=s[x+1][3]=1;
		}
		else if(y<=1){
			s[x][3]=s[x][m]=1;
		}
		else if(y==m-2){
			s[x+1][2]=1;s[x][m]=1;
		}
		else{
			s[x+1][1]=1;s[x][m-1]=1;
		}
		return;
	}
}
int main(){
	#ifndef ONLINE_JUDGE
	//freopen("a.in","r",stdin);
	//freopen("a.out","w",stdout);
	#endif
	int T=read();
	int tim(0),f(0);
	while(T--){
		flag=0;
		n=read();m=read();k=read();
		++tim;
		//if(tim==1) f=n==12&&m==12&&k==400;
		//assert(n<5&&m<5);
		//++tim;
		//if(oo==100&&tim>=60) 
		//if(f&&tim>=46) printf("%d %d %d\n",n,m,k);
		//if(f) continue;
		//if(oo==100) continue;
		if(n<5&&m<5){
			bf();continue;
		}
		bool jd(0);
		if(n>m) swap(n,m),jd=1;
		if(n==3&&k==8*(m-1)-8){
			if(!jd){
				for(int i=1;i<=n;i++){
					for(int j=1;j<=m;j++) putchar(j==m?'.':'*');
					putchar('\n');
				}
			}
			else{
				for(int j=1;j<=m;j++){
					for(int i=1;i<=n;i++) putchar(j==1?'.':'*');
					putchar('\n');
				}
			}
			putchar('\n');
			continue;
		}
		for(int i=1;i<=n;i++){
			s[i].clear();s[i].shrink_to_fit();
			s[i].resize(m+10);
			for(int j=1;j<=m;j++) s[i][j]=i==1;
		}
		for(int i=2;i<=n;i++){
			int o=0;
			for(int j=1;j<=m;j++){
				//printf("(%d %d) k=%d\n",i,j,k);
				if(i==n&&m-j+1<=5){
					o=1;work1();break;
				}
				if(k<4){
					o=1;work2(i,j);break;
				}
				s[i][j]=1;
				if(j==1) k-=1;
				else if(j==m) k-=3;
				else k-=4;
			}
			if(o) break;
		}
		if(!flag){
			printf("-1\n");
			putchar('\n');
			continue;
		}
		if(!jd){
			for(int i=1;i<=n;i++){
				for(int j=1;j<=m;j++) putchar(s[i][j]?'*':'.');
				putchar('\n');
			}
		}
		else{
			for(int j=1;j<=m;j++){
				for(int i=1;i<=n;i++) putchar(s[i][j]?'*':'.');
				putchar('\n');
			}
		}
		putchar('\n');
	}
	
	return 0;
}
/*
*/
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值