Greedy:Fence Repair(POJ 3252)

问题大意:农夫约翰为了修理栅栏,要将一块很长的木块切割成N块,准备切成的木板的长度为L1,L2...LN,未切割前的木板的长度恰好为切割后木板的长度的总和,每次切断木板的时候,需要的开销为这块木板的长度,例如长度为21的木板需要切成长度为5,8,8的三块木板,长为21的木板切成长为13和8的板时,开销为21,。再将长度为13的板切成长度为5和8的板时,开销是13,于是合计开销是34,然后要你求切割完的最小开销是什么。
乍眼看这一道题好像有很多种切割方案,似乎是很难解决的,但是我们这样想,就是当我们切一块木板的时候,我们所用的开销就是切割这一块木板所要用到的长度,我们得到了两块木板,这两块木板可以继续切的话,他们的总开销就是这两块木板的和,也就是一块长的木板。那么我们想到最后,就会发现其实就是我们得到了一个这样的东西,就是最小的板会所要用到的开销会占N次(视通过多少次分割得到这块板来定),如果我们要画一幅图来展示这个过程的话。。。

上面最大的开销是34=8*2+5*2+8(也就是二叉树的树叶对应节点大小乘以高度)
那么为了得到最小的开销,我们很容易就发现,我们只要把相对较小的节点放在比较深的地方就可以了,这是一种比较常用的贪婪的思想,证明我就省略了
那么现在我们只用不断地把最小的节点结合起来,最后就会形成最小的开销,那么不断找最小嘛,很容易就想到用堆,堆呢你可以自己写(熟练的话会很快),也可以直接用std(会比较简洁)
#include<stdio.h>
#include<stdlib.h> typedef int Position, *Heap; int Delete_Min(Heap, int *const);
void Push(Heap, int, int *const); int main(void)
{
int N, i, size = ;
int L1, L2, tmp;
long long ans = ; while (~scanf("%d",&N))
{
Heap pque = (Heap)malloc(sizeof(int)*N);
for (i = ; i < N; i++)
{
scanf("%d", &tmp);
Push(pque, tmp, &size);
}
while (size > )
{
L1 = Delete_Min(pque, &size);
L2 = Delete_Min(pque, &size); ans += (long long)L1 + L2;
Push(pque, L1 + L2, &size);
}
free(pque);
printf("%lld\n", ans);
}
} int Delete_Min(Heap heap,int *const size)
{
Position pr = , s1, s2, s;
int out = heap[], tmp = heap[(*size)--];
for (; pr <= *size;)
{
s1 = pr << ; s2 = s1 + ;
if (s2 <= *size)
{
if (heap[s1] < heap[s2]){ heap[pr] = heap[s1]; pr = s1; }
else{ heap[pr] = heap[s2]; pr = s2; }
}
else
{
if (s1 <= *size){ heap[pr] = heap[s1]; pr = s1;break; }
else break;
}
}
for (s = pr; s > ;)
{
if (s % == )
{
pr = s >> ;
if (heap[pr] > tmp) { heap[s] = heap[pr];s = pr;}
else break;
}
else
{
pr = (s - ) >> ;
if (heap[pr] > tmp){ heap[s] = heap[pr];s = pr; }
else break;
}
}
heap[s] = tmp;
return out;
} void Push(Heap heap, int item, int *const size)
{
Position s = ++(*size), pr;
for (; s > ;)
{
if (s % == )
{
pr = s >> ;
if (heap[pr] > item) { heap[s] = heap[pr]; s = pr; }
else break;
}
else
{
pr = (s - ) >> ;
if (heap[pr] > item){ heap[s] = heap[pr]; s = pr; }
else break;
}
}
heap[s] = item;
}
这是直接写堆的代码
#include<iostream>
#include<queue>
#include<functional>
#include<cstdio> using namespace std; int main(void)
{
int N, i;
int L1, L2, tmp;
long long ans = ; while (~scanf("%d", &N))
{
priority_queue<int, vector<int>, greater<int> >pque;
for (i = ; i < N; i++)
{
scanf("%d", &tmp);
pque.push(tmp);
}
while (pque.size() > )
{
L1 = pque.top();
pque.pop();
L2 = pque.top();
pque.pop(); ans += (long long)L1 + L2;
pque.push(L1 + L2);
};
printf("%lld\n", ans);
}
}
这是用的std,事实上呢用std是挺方便的,虽然稍微损失了一下性能,我直接用堆是472K,32ms,用std是920k,47ms,相差不大
另外这个思想还可以用来做著名的Huffman编码,其实Huffman以前写了一个,以后会贴出来看看
Greedy:Fence Repair(POJ 3252)的更多相关文章
- Fence Repair(poj 3253)
题意: 有一个农夫要把一个木板钜成几块给定长度的小木板,每次锯都要收取一定费用,这个费用就是当前锯的这个木版的长度 给定各个要求的小木板的长度,及小木板的个数n,求最小费用 提示: 以 3 5 8 5 ...
- POJ 3253 Fence Repair(修篱笆)
POJ 3253 Fence Repair(修篱笆) Time Limit: 2000MS Memory Limit: 65536K [Description] [题目描述] Farmer Joh ...
- poj 3253:Fence Repair(堆排序应用)
Fence Repair Time Limit: 2000MS Memory Limit: 65536K Total Submissions: 23913 Accepted: 7595 Des ...
- POJ 30253 Fence Repair (二叉树+优先队列)
题目链接 Description Farmer John wants to repair a small length of the fence around the pasture. He meas ...
- Fence Repair (二叉树求解)(优先队列,先取出小的)
题目链接:http://poj.org/problem?id=3253 Fence Repair Time Limit: 2000MS Memory Limit: 65536K Total Sub ...
- poj 3253 Fence Repair (STL优先队列)
版权声明:本文为博主原创文章,未经博主同意不得转载. vasttian https://blog.csdn.net/u012860063/article/details/34805369 转载请注明出 ...
- Round Numbers(poj 3252)
题意:算出区间内二进制中0的个数大于等于1的个数的数字有多少个 /* 本来以为用数位DP搞,但是组合数更简单. 我们设n的二进制长度为len. ①:先考虑长度小于len的数字. 这里以数字22为例,二 ...
- poj-3253 fence repair(贪心题)
题目描述: Farmer John wants to repair a small length of the fence around the pasture. He measures the fe ...
- POJ 3253 Fence Repair (优先队列)
POJ 3253 Fence Repair (优先队列) Farmer John wants to repair a small length of the fence around the past ...
随机推荐
- 洛谷P1130 红牌
题目描述 某地临时居民想获得长期居住权就必须申请拿到红牌.获得红牌的过程是相当复杂 ,一共包括N个步骤.每一步骤都由政府的某个工作人员负责检查你所提交的材料是否符合条件.为了加快进程,每一步政府都派了 ...
- [HNOI2010]BOUNCE 弹飞绵羊
题目描述 某天,Lostmonkey发明了一种超级弹力装置,为了在他的绵羊朋友面前显摆,他邀请小绵羊一起玩个游戏.游戏一开始,Lostmonkey在地上沿着一条直线摆上n个装置,每个装置设定初始弹力系 ...
- Android消息通知(notification)和PendingIntent传值
通知栏的自定义布局:转:http://blog.csdn.net/vipzjyno1/article/details/25248021 拓展 实现自定义的通知栏效果: 这里要用到RemoteViews ...
- jboss7 添加虚拟目录 上传文件路径
直接在jboss-as-7.1.1.Final\welcome-content\下加个子目录: jboss-as-7.1.1.Final\welcome-content\logs. 即可访问.
- repo 无法连接gerrit.googlesource.com 下载工具
万恶的墙下,我们可以用其他的url来下载代码. 屏蔽掉repo里面的 #REPO_URL = 'https://gerrit.googlesource.com/git-repo' 在你的下载连接后添加 ...
- MySql批处理的小窍门:排行榜类数据生成
MySql批处理的小窍门:排行榜类数据生成 最近在做新版本的开发,其中涉及到排行榜的批量预生成,在此分享给大家. 关键点 名次的计算(不考虑用游标) 单榜单查询 对于排行榜这种类型的数据,当只查一个排 ...
- Boost的状态机库教程(1)
介绍 Boost状态机库一个应用程序框架,你可以用它将UML状态图快速的转换为可执行的c++代码,而不需要任何的代码生成器.它支持几乎所有的UML特征,可以直接了当的转换,并且转换后的c++代码就像对 ...
- LWP 轻量级线程的意义与实现
转子 http://www.ibm.com/developerworks/cn/linux/kernel/l-thread/ 二.Linux 2.4内核中的轻量进程实现 最初的进程定义都包含程序.资源 ...
- C++对象模型:单继承,多继承,虚继承
什么是对象模型 有两个概念可以解释C++对象模型: 语言中直接支持面向对象程序设计的部分.对于各种支持的底层实现机制. 类中成员分类 数据成员分为静态和非静态,成员函数有静态非静态以及虚函数 clas ...
- 防止ajax请求重发
debounce ajax请求,防止用户点击过快造成重发 按钮disabled处理,显示loading,防止用户失去耐心,重复点击 表单提交也可以同样处理.