sgu 148 分类: sgu 2015-03-11 13:14 49人阅读 评论(0) 收藏
2015-03-11 13:14
405 查看
假设每一层的水都是本质不同的,
如果存在一种最优方案从第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(i−1)>v(j)
=>pre(j)−v(j)>pre(i−1)
当对第i层减压时
totcost=sumc(i,n)−ncost(i)
ncost(i)=Σcost(j) | pre(j)−v(j)>pre(i−1) & i<j<=n
因为pre(i)是单调上升的,
而注意到第 j 层自动减压的条件:
pre(j)−v(j)>pre(i−1)& i<j<=n
所以 ncost(i) 是单调下降的
所以可以有这样一个算法:
1,处理 pre()
2,处理 ncost() ,维护一个大根堆,储存key=pre(j)−v(j)和cost(j)
从 n 到 1 枚举 i,ncost(i)=ncost(i+1)
ncost(i)+=heap[top].cost,pop(top) | pre(i−1)<heap[top].key
3,枚举减压起始层,计算代价,求出最优方案
时间复杂度O(N∗logN)。
如果存在一种最优方案从第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(i−1)>v(j)
=>pre(j)−v(j)>pre(i−1)
当对第i层减压时
totcost=sumc(i,n)−ncost(i)
ncost(i)=Σcost(j) | pre(j)−v(j)>pre(i−1) & i<j<=n
因为pre(i)是单调上升的,
而注意到第 j 层自动减压的条件:
pre(j)−v(j)>pre(i−1)& i<j<=n
所以 ncost(i) 是单调下降的
所以可以有这样一个算法:
1,处理 pre()
2,处理 ncost() ,维护一个大根堆,储存key=pre(j)−v(j)和cost(j)
从 n 到 1 枚举 i,ncost(i)=ncost(i+1)
ncost(i)+=heap[top].cost,pop(top) | pre(i−1)<heap[top].key
3,枚举减压起始层,计算代价,求出最优方案
时间复杂度O(N∗logN)。
#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 }
相关文章推荐
- sgu143 分类: sgu 2015-03-11 22:11 38人阅读 评论(0) 收藏
- sgu 193 分类: sgu 2015-03-11 18:38 45人阅读 评论(0) 收藏
- sgu 179 分类: sgu 2015-03-11 21:25 32人阅读 评论(0) 收藏
- sgu195 分类: sgu 2015-04-30 21:39 29人阅读 评论(0) 收藏
- CocoaPods安装和使用教程 分类: ios技术 ios相关 2015-03-11 21:53 48人阅读 评论(0) 收藏
- sgu 128 分类: sgu 2015-03-13 13:56 44人阅读 评论(0) 收藏
- sgu 138 分类: sgu 2015-03-16 18:32 40人阅读 评论(0) 收藏
- 如何发布android应用程序 分类: Android开发 2014-05-30 10:53 49人阅读 评论(0) 收藏
- sgu 162 分类: sgu 2015-04-25 13:27 39人阅读 评论(0) 收藏
- sgu 120 分类: sgu 2015-02-09 17:19 106人阅读 评论(0) 收藏
- sgu220&sgu221 分类: sgu 2015-06-15 22:01 24人阅读 评论(0) 收藏
- sgu 259 分类: sgu 2015-06-17 01:50 19人阅读 评论(0) 收藏
- sgu 172 分类: sgu 2015-03-08 17:34 35人阅读 评论(0) 收藏
- sgu222 分类: sgu 2015-06-12 09:27 24人阅读 评论(0) 收藏
- sgu122 分类: sgu 2015-02-15 11:39 71人阅读 评论(0) 收藏
- sgu 228 分类: sgu 2015-06-21 17:10 25人阅读 评论(0) 收藏
- sgu 141 分类: sgu 2015-03-16 19:36 39人阅读 评论(0) 收藏
- sgu200 分类: sgu 2015-05-25 18:53 32人阅读 评论(0) 收藏
- 单链表的拆分 分类: 链表 2015-06-07 13:14 19人阅读 评论(0) 收藏
- sgu 225 分类: sgu 2015-06-15 19:24 16人阅读 评论(0) 收藏