UVALive 6424 Russian Dolls(贪心)

本文探讨了在给定俄罗斯套娃的体积、内部空隙和单位空隙成本的情况下,如何通过优化排列方式来最小化整体成本。通过引入贪心策略和费用流的概念,实现对玩偶内部空间的有效利用,最终确定最小成本排列方案。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

6424 Russian Dolls
Maybe you know the famous russian souvenir Russian Dolls. It looks like a set of nested wooden dolls.
A doll with a smaller size is placed inside a bigger one. Let's consider all dolls taken apart. Each
doll has an outer volume outi which is the volume it occupies in space and an inner volume ini | the
volume of the empty space inside the doll. You may assume that you can put one doll inside another
if the outer volume of the rst doll is strictly less than the inner volume of the second one. If two or
more dolls are inside another one they can't lie one near the other, they must be nested.
For each doll the cost of unit of empty space | costi is known. You must pay exactly costi for each
unit of empty space which directly belongs to the i-th doll (but not to ones inside it). You may arrange
the dolls the way you want as long as you are not contradicting the rules. The objective is to nd an
arrangement of nesting the dolls (not necessarily all of them) such that the overall cost you have to pay
is minimized.
Input
The input le contains several test cases, each of them as described below.
First line contains an integer N (1 N 1000) which is the number of dolls you have. The i-th
of the next N lines contains three integers outi, ini, costi (1 ini < outi 1000, 1 costi 1000),
which are the outer volume, inner volume and the empty space cost of the i-th doll.
Sample Output
For each test case, write to the output a single integer P which is the minimum possible cost you should
pay on a line by itself.
Sample Input
3
5 4 1
4 2 2
3 2 1
Sample Output

7


题意:n个玩偶,每个玩偶有三个值:(第i个)外体积out(i),内部空体积in(i),单位空空体积的花费为cost(i)。第j个玩偶能放在第i个玩偶内部必须满足条件:out(j)<in(i)。一个玩偶内部要放多个玩偶,必须通过嵌套的方式。也就是说一个玩偶的内部空间如果存在多个玩偶,那么这些玩偶一定是嵌套的,不会存在两个玩偶并列在一个玩偶内部。设第i个玩偶内部的玩偶是x,那么第i个玩偶的花费为cost(i)*(in(i)-out(x))。最后问总花费最小可以为多少?

题解:总花费的公式可以写成:sum(cost(i)*(in(i)-out( i ')) ,1<=i<=n )。out(i')为放在第i个玩偶内部的玩偶的体积,如果 i!=j ,那么i'!=j' 。

我们还可以把公式展开成这种形式:sum(cost(i)*in(i))-sum(cost(i)*in(i')) 。前面一部分为定值,实际上我们要让后面一部分sum(cost(i)*in(i'))最大。容易想到这是个带权匹配问题,可以用费用流解决,但是复杂度显然太高。对于第i个玩偶来说,我们要让cost(i)*in(i') 最大的话,一定是贪心找满足条件的最大的 in(i‘) ,设i'=x。但是目前只是让第i个玩偶的值最大,有可能存在一个玩偶j,x能放在j里面,并且cost(j)>cost(i),那么cost(j)*in(x)>cost(i)*in(x),把x放在j更优。所以若cost(i)是所有玩偶中最大的,那么前面的贪心策略就一定是正确的。

代码如下:

#include<stdio.h>
#include<iostream>
#include<algorithm>
#include<map>
#include<list>
#include<queue>
#include<string.h>
#define nn 1100
#define inff 0x3fffffff
using namespace std;
typedef long long LL;
struct node
{
    int out,in,cost;
}a[nn];
int n;
bool cmp(node x,node y)
{
    if(x.cost==y.cost)
        return x.in>y.in;
    return x.cost>y.cost;
}
bool use[nn];
int main()
{
    int i,j;
    while(scanf("%d",&n)!=EOF)
    {
        for(i=1;i<=n;i++)
        {
            scanf("%d%d%d",&a[i].out,&a[i].in,&a[i].cost);
        }
        sort(a+1,a+n+1,cmp);
        memset(use,false,sizeof(use));
        int ans=0;
        for(i=1;i<=n;i++)
        {
            int ix=0;
            int id=-1;
            for(j=1;j<=n;j++)
            {
                if(!use[j]&&a[j].out<a[i].in)
                {
                    if(a[j].out>ix)
                    {
                        id=j;
                        ix=a[j].out;
                    }
                }
            }
            if(id!=-1)
                use[id]=true;
            ans+=a[i].cost*(a[i].in-ix);
        }
        printf("%d\n",ans);
    }
    return 0;
}


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值