UPC22级训练赛十四场

 本人是个刚接触算法的小菜鸡 这也是我的第一个博客 这道题在一个大佬的指导下顺利完成 太高兴了 所以发一个博客

问题 J: 矩形覆盖

(这里所有的矩形,就相当于一个长方形)学校门口路面上出现了一个矩形大洞。现在学校找来了一些矩形钢板,想要盖住这个大洞。可是,他们又想不出一个既安全又节省的覆盖方案,所以,找到了参加程序设计竞赛的你,帮忙设计一个覆盖方案。从安全角度考虑,钢板的放置必须符合如下所有原则:
1.钢板之间可以相互叠加。
2.钢板必须完全覆盖大洞。
3.你可以任意旋转每块钢板,但是覆盖过程中,钢板的边必须与大洞的边平行。
4.每块钢板的4个角必须严格落在大洞外(钢板任何一个角和洞口的角重合,或者在大洞内部,这块钢板就会不稳定)如下图所示几种放置方法,黑色表示大洞区域,红色表示钢板:

图A和B中,都有钢板的点在大洞内部,不能这样放置。图C和D中,钢板4个角都在大洞外,是稳定安全的。图E中,也是不稳定的,就算钢板的角在其他钢板上,也要落在大洞外。请问能否在安全的前提下,用这些钢板盖住这个大洞,若可以,使用最少的钢板数量进行覆盖。请你帮忙计算一下!

输入

第一行两个整数R和C,表示大洞的长和宽。
第二行一个整数N,表示矩形钢板数量
接下来N行,每行两个整数w[i]和h[i],表示第i块钢板的长和宽。

输出

要覆盖大洞最少使用钢板的数量,若无法覆盖,输出-1.

样例输入 Copy

【样例1】
5 5
3
8 2
8 3
8 4
【样例2】
10 10
4
6 6
6 6
6 6
6 6

样例输出 Copy

【样例1】
2
【样例2】
-1

提示

样例1解释:任意选择两个钢板就可以盖住这个大洞。例如用最小的两个(8,2)和(8,3)钢板刚好覆盖如下图:

样例2解释:无法覆盖,任何一个钢板都无法放上去。无法使钢板的四个角都落在大洞外。

30%的数据,1<=R,C<=1000,1<=w[i]<=1000,h[i]=1。
70%的数据,n<=20,1<=R,C<=1000,1<=w[i],h[i]<=1000。
100%的数据1<=n<=50,1<=R,C,w[i],h[i]<=1000000000。

 代码附上 思路应该还算清晰吧 

#include<bits/stdc++.h>
using namespace std;
typedef pair<int,int>PII;
PII L[55];
PII D[55],Z[55];
int main()
{
    int a,b;
    cin>>a>>b;
    int n,t1=0,t2=0;
    cin>>n;
    if(b>a)swap(a,b);
    for(int i=0;i<n;i++){
        int x,y;
        cin>>x>>y;
        if(y>x)swap(y,x);
        Z[i].first=x;
        Z[i].second=y;
    }//以宽来覆盖
    for(int i=0;i<n;i++){
        if(Z[i].second>b){
            D[t1].first=Z[i].first;
            D[t1].second=Z[i].second;
            t1++;
        }else if(Z[i].first>b){
            D[t1].first=Z[i].second;
            D[t1].second=Z[i].first;
            t1++;
        }
    }
    for(int i=0;i<n;i++){
        if(Z[i].second>a){
            L[t2].first=Z[i].first;
            L[t2].second=Z[i].second;
            t2++;
        }else if(Z[i].first>a){
            L[t2].first=Z[i].second;
            L[t2].second=Z[i].first;
            t2++;
        }
    }
    sort(L,L+t2);
    sort(D,D+t1);
    t1--,t2--;
    int ans1=0,ans2=0;
    while(t1>=0&&a>0){
        a-=D[t1].first;
        ans1++;
        t1--;
    }
    while(t2>=0&&b>0){
        b-=L[t2].first;
        ans2++;
        t2--;
    }
    if(a>0&&b>0){
        cout<<"-1";
    }else if(a<=0&&b>0){
        cout<<ans1;
    }else if(a>0&&b<=0){
        cout<<ans2;
    }else if(a<=0&&b<=0){
        cout<<min(ans1,ans2);
    }
	return 0;
}

 

 

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值