POJ3253 Fence Repair 小顶堆+贪心

给了你N个木棒,求把他们组装成一根需要的最小花费,每次只能选两根组装在一起,需要的花费为两个木棒之和,

以前遇到过把一整根切开的,那个是DP,这个则有些类似,可是大胆的猜测了一下,直接每次选取所有木棒中最短的两根,这样就可以了,那么贪心是适用的,但是数量很多,而且两根最短的组装好了得插回去,这样不可能每次都排序吧,

这题首先优先队列肯定是可以做的,

最小堆也是可以的,每次都选出堆里的最小的两个求和再放回去即可

队列本身也就是堆吧,所以差别不大,但是没用过最小堆最大堆的 所以用一次把

#include<iostream>
#include<cstdio>
#include<list>
#include<algorithm>
#include<cstring>
#include<string>
#include<stack>
#include<map>
#include<vector>
#include<cmath>
#include<memory.h>
#include<set>
#include<cctype>
#include<queue>

#define ll long long
#define LL __int64
#define eps 1e-8

//const ll INF=9999999999999;

#define inf 0xfffffff

using namespace std;

//vector<pair<int,int> > G;
//typedef pair<int,int> P;
//vector<pair<int,int>> ::iterator iter;
//
//map<ll,int>mp;
//map<ll,int>::iterator p;

LL len[20000 + 5];//小顶堆里的元素,注意len[0]代表小顶堆的元素数目

void clear() {
	memset(len,0,sizeof(len));
}

/****构建小顶堆****/
void heap(int i) {
	int l = i * 2;
	int r = i * 2 + 1;
	int minn = i;
	if(l <= len[0] && len[l] < len[minn])
		minn = l;
	if(r <= len[0] && len[r] < len[minn])
		minn = r;
	if(i != minn) {
		int tmp = len[i];
		len[i] = len[minn];
		len[minn] = tmp;
		heap(minn);
	}
}

/******插入小顶堆*****/
void insertheap(LL x) {
	len[++len[0]] = x;
	LL tmp = len[0];
	while(tmp > 1 && len[tmp] < len[tmp/2]) {
		int t = len[tmp];
		len[tmp] = len[tmp/2];
		len[tmp/2] = t;
		tmp >>= 1;
	}
}

LL get() {
	LL ans1 = len[1];
	len[1] = len[len[0]];//拿走第一个以后,把堆尾的拿到堆首
	len[0]--;
	heap(1);//重新排序
	LL ans2 = len[1];
	len[1] = len[len[0]];
	len[0]--;
	heap(1);
	insertheap(ans1 + ans2);//取出第一小第二小的,然后相加以后再插回小顶堆
	return ans1 + ans2;
}

int main() {
	int n;
	while(scanf("%d",&n) == 1) {
		clear();
		for(int i=1;i<=n;i++) {
			scanf("%I64d",&len[i]);
			insertheap(len[i]);
		}
		LL ans = 0;
		for(int i=1;i<n;i++)
			ans += get();//注意i不能等于n,最后一次拼好就不用放回小顶堆里了
		printf("%I64d\n",ans);
	}
	return 0;
}

POJ3253 Fence Repair 小顶堆+贪心

时间: 2024-10-26 20:10:17

POJ3253 Fence Repair 小顶堆+贪心的相关文章

优先队列 poj3253 Fence Repair

Fence Repair Time Limit: 2000MS   Memory Limit: 65536K Total Submissions: 51411   Accepted: 16879 Description Farmer John wants to repair a small length of the fence around the pasture. He measures the fence and finds that he needs N (1 ≤ N ≤ 20,000)

poj3253 Fence Repair STL优先队列

转载请注明出处:http://blog.csdn.net/u012860063 题目链接:http://poj.org/problem?id=3253 Description Farmer John wants to repair a small length of the fence around the pasture. He measures the fence and finds that he needs N (1 ≤ N ≤ 20,000) planks of wood, each

wikioi 1245 小顶堆

题目描述 Description 有两个长度为 N 的序列 A 和 B,在 A 和 B 中各任取一个数可以得到 N^2 个和,求这N^2 个和中最小的 N个. 输入描述 Input Description 第一行输入一个正整数N:第二行N个整数Ai 且Ai≤10^9:第三行N个整数Bi, 且Bi≤10^9 输出描述 Output Description 输出仅一行,包含 n 个整数,从小到大输出这 N个最小的和,相邻数字之间用 空格隔开. 样例输入 Sample Input 5 1 3 2 4

heap c++ 操作 大顶堆、小顶堆

在C++中,虽然堆不像 vector, set 之类的有已经实现的数据结构,但是在 algorithm.h 中实现了一些相关的模板函数.下面是一些示例应用 http://www.cplusplus.com/reference/algorithm/pop_heap/ #include <iostream> #include <algorithm> // make_heap(), pop_heap(), push_heap() #include <vector> using

python 大顶堆 小顶堆

http://www.coder4.com/archives/3844 需1求:给出N长的序列,求出TopK大的元素,使用小顶堆,heapq模块实现. import heapq import random class TopkHeap(object): def __init__(self, k): self.k = k self.data = [] def Push(self, elem): if len(self.data) < self.k: heapq.heappush(self.data

BZoj 1293 生日礼物(小顶堆)

传送门:http://acm.hust.edu.cn/vjudge/problem/viewProblem.action?id=27400 Anayse:小顶堆: 1 1 5     - >    1 3 5     ->    3 5 7    ->     5 7 8 pop(1)    p(1)      p(3)       最优解. 每次剔除堆顶,然后换push与堆顶相同种类的珠子,由于单调,,距离会被缩短,于是找出最优解.详见上式. push()  log(n) so,复杂度

wikioi 2573 大顶堆与小顶堆并用

题目描述 Description 我们使用黑匣子的一个简单模型.它能存放一个整数序列和一个特别的变量i.在初始时刻,黑匣子为空且i等于0.这个黑匣子能执行一系列的命令.有两类命令: ADD(x):把元素x放入黑匣子:GET:把i加1的同时,输出黑匣子内所有整数中第i小的数.牢记第i小的数是当黑匣子中的元素已非降序排序后位于第i位的元素. 下面的表6_4是一个11个命令的例子: 表6_4 编号 命令 i 黑匣子内容 输出 1 ADD(3) 0 3 2 GET 1 3 3 3 ADD(1) 1 1,

优先级队列(小顶堆)的dijkstra算法

php实现迪杰斯特拉算法,并由小顶堆优化 1 <?php 2 3 class DEdge 4 { 5 public $nextIndex, $length; 6 7 public function __construct($nextIndex, $length) 8 { 9 $this->nextIndex = $nextIndex; 10 $this->length = $length; 11 } 12 } 13 14 class DNode 15 { 16 public $index

剑指offer:数据流中的中位数(小顶堆+大顶堆)

1. 题目描述 /** 如何得到一个数据流中的中位数? 如果从数据流中读出奇数个数值,那么中位数就是所有数值排序之后位于中间的数值. 如果从数据流中读出偶数个数值,那么中位数就是所有数值排序之后中间两个数的平均值. 我们使用 Insert()方法读取数据流,使用 GetMedian()方法获取当前读取数据的中位数. */ 2. 思路 /** 最大堆和最小堆 * 每次插入小顶堆的是当前大顶堆中最大的数 * 每次插入大顶堆的是当前小顶堆中最小的数 * 这样保证小顶堆中的数永远大于等于大顶堆中的数(值