Codeforces Round #413 D. Field expansion (搜索)

In one of the games Arkady is fond of the game process happens on a rectangular field. In the game process Arkady can buy extensions for his field, each extension enlarges one of the field sizes in a particular number of times. Formally, there are n extensions, the i-th of them multiplies the width or the length (by Arkady’s choice) by ai . Each extension can’t be used more than once, the extensions can be used in any order.

Now Arkady’s field has size h × w. He wants to enlarge it so that it is possible to place a rectangle of size a × b on it (along the width or along the length, with sides parallel to the field sides). Find the minimum number of extensions needed to reach Arkady’s goal.

题意

将原 h×w 的矩形扩展,使得其能够放置 a×b 的矩形。每次扩展可以从给定的 n ( n100000 ) 个数中选择一个数 Ai ,将 hhAi 或者 wwAi ,其中每个数最多只能使用一次,问最少扩展多少次能满足条件,或不可能。

解题思路

首先可以想到,对于同样地对原矩形扩展 X 次,使用 n 个数中最大的 X 个数对矩形进行扩展必然是最优的。因此,对 n 个数从小到大进行排序,并优先选用可用的最大数。

给定的 n 个数对原 h×w 矩形进行扩展,则每次可以将 h 或 w 扩展 Ai 倍。因此,朴素地使用搜索的复杂度将可能达到 O(2100000) 。但是,对于 2Ai ,且 1a,b,h,w100000 ,故 log210000017 ,即复杂度实际应该在 O(234) 。当然,这仍然无法满足。

考虑对问题进行优化,当经过处理的原矩形 H×W 使得可用的 Ai 都为 2 时,此时无需考虑将 2 如何分配的问题,当 H 或 W 尚有不足时,直接 ×2 即可;同时 log3100000=11 O(222) 可在 1000 ms 内解决。故特判 2 可将问题复杂度缩小到可解范围。

代码

#include<bits/stdc++.h>
using namespace std;
int a, b, h, w, n, A[100010];
int dfs(long long h, long long w, int idx)
{
    if(h>=a&&w>=b)    return n-idx;
    if(idx==0)  return -1;
    if(A[idx] == 2)
    {
        if(h<a) return dfs(h*2, w, idx-1);
        return dfs(h, w*2, idx-1);
    }
    else
    {
        int ansh = -1, answ = -1;
        if(h<a)
            ansh = dfs(h*A[idx], w, idx-1);
        if(w<b)
            answ = dfs(h, w*A[idx], idx-1);
        if(ansh==-1 || answ==-1)    return max(ansh, answ);
        return min(ansh, answ);
    }
}
int main()
{
    scanf("%d %d %d %d %d",&a,&b,&h,&w,&n);
    for(int i=1;i<=n;i++)
        scanf("%d",&A[i]);
    sort(A+1, A+n+1);
    int ansl, ansr;
    ansl = dfs(h, w, n);
    swap(a, b);
    ansr = dfs(h, w, n);
    if(ansl==-1 || ansr==-1)    printf("%d\n", max(ansl, ansr));
    else    printf("%d\n", min(ansl, ansr));
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值