sgu 148 分类: sgu 2015-03...


假设每一层的水都是本质不同的,

如果存在一种最优方案从第i层开始减压,那么第i层的水一定要流到第n层

可以用反证法证明:
若存在一种最优方案第i层的水没有流到第 n 层,
而是在第j层被阻挡了 (j>i)

那么修改这个方案,从第j+1层开始减压 , 第 j+1 到第 n 层的操作不变,
代价更小,而最后的效果相同,
所以这不是最优方案,推出矛盾,原结论成立。

于是可以枚举 i,从第 i 层开始减压,计算代价,选出代价最小的方案
时间复杂度 O(n2),但这里n的范围较大,会超时

可以有优化
如果从第 i 层开始减压,第 j 层自动减压的条件是sumw(i,j)>v(j)

pre(j)pre(i1)>v(j)

=>pre(j)v(j)>pre(i1)

当对第i层减压时
totcost=sumc(i,n)ncost(i)

ncost(i)=Σcost(j) | pre(j)v(j)>pre(i1) & i<j<=n

因为pre(i)是单调上升的,
而注意到第 j 层自动减压的条件:
pre(j)v(j)>pre(i1)& i<j<=n

所以 ncost(i) 是单调下降的

所以可以有这样一个算法:

1,处理 pre()

2,处理 ncost() ,维护一个大根堆,储存key=pre(j)v(j)cost(j)
n1 枚举 incost(i)=ncost(i+1)
ncost(i)+=heap[top].costpop(top) | pre(i1)<heap[top].key

3,枚举减压起始层,计算代价,求出最优方案

时间复杂度O(NlogN)



#include<cstdio>
#include<cstdlib>
#include<queue>  
#include<utility>
using namespace std;

const int MAXN = 15005 , INF = (1<<30) - 1;

int n;
struct station{int w,l,p;}b[MAXN] = {0};

priority_queue<pair<int,int> > heap;

int pre[MAXN] = {0};

int ans , st , cost;

int main()
{
#ifndef ONLINE_JUDGE
    freopen("sgu148.in","r",stdin);
    freopen("sgu148.out","w",stdout);
#endif

    scanf("%d",&n);

    for(int i = 1; i <= n ;i++)
    {
        scanf("%d%d%d",&b[i].w,&b[i].l,&b[i].p);
        pre[i] = pre[i-1] + b[i].w;
    }
//  sum(j , i) > L(i)   pre[i] - pre[j-1] > L[i]  
//  pre[j-1] < pre[i] - L[i]  
    cost = 0 , st = 0 ,ans = INF; 

    for(int i = n; i >= 1;i--)
    {
        for(;!heap.empty() && heap.top().first > pre[i-1];heap.pop())
           cost -= heap.top().second;

        heap.push(make_pair(pre[i] - b[i].l , b[i].p));

        cost += b[i].p;

        if(cost < ans)
        {
            ans = cost;
            st = i;
        }
    }
    for(int i = st , sumf = 0; i <= n; i++)
    {
        sumf += b[i].w;

        if(sumf <= b[i].l)
          printf("%d\n",i);
    }


#ifndef ONLINE_JUDGE        
    fclose(stdin);
    fclose(stdout);
#endif  
}

版权声明:本文为博主原创文章,未经博主允许不得转载。

转载于:https://www.cnblogs.com/dashgua/p/4723086.html

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值