[2014.3.30]poj3253 Fence Repair 解题报告(C++)

来源:互联网 发布:手机数据迁移软件 编辑:程序博客网 时间:2024/06/05 02:16

【原题】

[Description]

Farmer John wants to repair a small length of the fence around the pasture. He measures the fence and finds that he needsN (1 ≤N ≤ 20,000) planks of wood, each having some integer lengthLi (1 ≤Li ≤ 50,000) units. He then purchases a single long board just long enough to saw into theN planks (i.e., whose length is the sum of the lengthsLi). FJ is ignoring the "kerf", the extra length lost to sawdust when a sawcut is made; you should ignore it, too.

FJ sadly realizes that he doesn't own a saw with which to cut the wood, so he mosies over to Farmer Don's Farm with this long board and politely asks if he may borrow a saw.

Farmer Don, a closet capitalist, doesn't lend FJ a saw but instead offers to charge Farmer John for each of theN-1 cuts in the plank. The charge to cut a piece of wood is exactly equal to its length. Cutting a plank of length 21 costs 21 cents.

Farmer Don then lets Farmer John decide the order and locations to cut the plank. Help Farmer John determine the minimum amount of money he can spend to create theN planks. FJ knows that he can cut the board in various different orders which will result in different charges since the resulting intermediate planks are of different lengths.

[Input]

Line 1: One integer N, the number of planks
Lines 2..N+1: Each line contains a single integer describing the length of a needed plank

[Output]

Line 1: One integer: the minimum amount of money he must spend to makeN-1 cuts

[Sample Input]

3858

[Sample Output]

34

[Hint]

He wants to cut a board of length 21 into pieces of lengths 8, 5, and 8.
The original board measures 8+5+8=21. The first cut will cost 21, and should be used to cut the board into pieces measuring 13 and 8. The second cut will cost 13, and should be used to cut the 13 into 8 and 5. This would cost 21+13=34. If the 21 was cut into 16 and 5 instead, the second cut would cost 16 for a total of 37 (which is more than 34).
【题意】长为L的木头锯成两半需要花L美分。把一根木头截成指定长度的一段一段,至少要花多少钱?

【思路】例如把长为L=L1+L2+L3的木头切成L1/L2/L3三段

             L

         /         \

   L1+L2    L3

   /       \

L1      L2,总共需要花钱L+L1+L2=L1*2+L2*2+L3*1,等于以成品长度为权值的节点构成的二叉树的带权外部路径长度,为了让带权外部路径最小,应该将这些节点构成哈夫曼树,按照哈夫曼树的指示去截木头。

【代码】

#include "stdafx.h"#include "iostream"#include "math.h"using namespace std;//找到长为n的数组a中最小值和次最小值的大小及位置//最小值min1,位置min1_i;次最小值min2,位置min2_ivoid find_min_i(int a[], int n, int &min1, int &min1_i, int &min2, int &min2_i){min1 = 1000000000;min2 = 1000000000;for(int i = 0; i < n; i++)//扫描整个数组{if(a[i] < min1)//如果小于当前最小值{min2 = min1;min2_i = min1_i;min1 = a[i];min1_i = i;}else if(a[i] < min2)//如果不小于当前最小值但是小于当前次最小值{min2 = a[i];min2_i = i;}}}int main(){int n;cin >> n;int* a = new int[n];for(int i = 0; i < n; i++)cin >> a[i];long long cost = 0;//花费的钱数,一定是long long,int范围不够while(n >= 2)//如果还需要合并{int min1, min1_i, min2, min2_i;find_min_i(a, n, min1, min1_i, min2, min2_i);//找到最小值和次最小值if(min1_i == n-1)//如果最小值在数组最后a[min2_i] = min1 + min2;//则新节点覆盖次最小值else if(min2_i == n-1)//如果次最小值在数组最后a[min1_i] = min1 + min2;//则新节点覆盖最小值else{a[min1_i] = a[n-1];//把数组最后的一个节点搬到前面来a[min2_i] = min1 + min2;//新节点}n--;//数组长度减1cost += (min1 + min2);//又要花钱};cout << cost << endl;delete[] a;}
【遗留问题】

求最小值和次最小值改用最小堆来做的话会变快吧?

0 0