“蔚来杯“2022牛客暑期多校训练营4-H-Wall Builder II

"蔚来杯"2022牛客暑期多校训练营4-H-Wall Builder II

题目大意

给定 T ( 1 ≤ T ≤ 100 ) T(1\le T\le 100) T(1T100) n ( 1 ≤ n ≤ 100 , n 的总和不超过 200 ) n(1\le n\le 100,n的总和不超过200) n(1n100,n的总和不超过200),表示有 n n n 1 × 1 1\times 1 1×1的积木, n − 1 n-1 n1 1 × 2 1\times 2 1×2的积木······ 2 2 2 1 × ( n − 1 ) 1\times (n-1) 1×(n1)的积木, 1 1 1 1 × n 1\times n 1×n的积木现要求将其全部拼成一个矩形,要求其周长最小,输出周长与每块积木左下角与右上角的坐标。每块积木不可旋转,即只可以横着放。

解题思路

可以发现对于每个 n n n,该矩阵面积不变,而 n n n的范围十分小,可以枚举矩阵的长和宽,然后判断其是否可实现。
考虑贪心,对于每次搭建,先用可用的最大积木。

代码实现

#include<bits/stdc++.h>
#define f first
#define s second
#define x first
#define y second
#define ll long long
using namespace std;
pair<pair<int,int>,pair<int,int> >a[10005];
ll n,T,b[105];
long long S;
int main(){
	cin>>T;
	while(T--){
		cin>>n;
        S=0;
		for(int i=1;i<=n;i++)b[i]=n-i+1,S+=b[i]*i;
		for(long long i=S/(ll)sqrt(S);i>=1;i--){
			for(int j=1;j<=n;j++)b[j]=n-j+1;
			if(S%i==0){
				ll cnt=n,k=i,sum=0;
				a[sum].f.x=a[sum].f.y=a[sum].s.x=a[sum].s.y=0;
				while(k){
					ll r=S/i,z=min(n,r);
					while(z&&r){
						
						while(b[z]&&r-z>=0){
							r-=z;
                            if(r+z==S/i)a[++sum].f.x=i-k,a[sum].f.y=0,a[sum].s.x=i-k+1,a[sum].s.y=a[sum].f.y+z;//直角坐标系没学好想,x,y反了,不过关系不大
                            else
							a[++sum].f.x=i-k,a[sum].f.y=a[sum-1].s.y,a[sum].s.x=i-k+1,a[sum].s.y=a[sum].f.y+z;
							b[z]--;
						}z=min(r,z-1);
					}
					if(r)break;
					k--;
				}
				if(k==0){
					cout<<(i+S/i)*2<<'\n';
					for(int j=1;j<=sum;j++)cout<<a[j].f.y<<' '<<a[j].f.x<<' '<<a[j].s.y<<' '<<a[j].s.x<<'\n';
					break;
				}
			}
		}
	}
} 
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值