pku上的一道ACM题

yeknight 2009-11-13 01:48:36
Fence Repair
Time Limit: 2000MS Memory Limit: 65536K
Total Submissions: 5861 Accepted: 1825

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 having some integer length Li (1 ≤ Li ≤ 50,000) units. He then purchases a single long board just long enough to saw into the N planks (i.e., whose length is the sum of the lengths Li). 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 the N-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 the N 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 make N-1 cuts
Sample Input

3
8
5
8
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).

我用的是构造哈夫曼树的方法,不知道为什么是WA

#include <iostream>
using namespace std;

const int MAX = 20001;
const int hufnum = 40002;
const int maxint = 60000;
int n;
int blanks[MAX];
__int64 sum;

typedef struct node
{
int weight;
int lchild;
int rchild;
int parent;
}huftree;
huftree tree[MAX*2];

void creattreehufman()
{
int i,j,p1,p2;
float least1,least2;

for(i = 1; i <= n * 2; i++)
{
tree[i].parent = 0;
tree[i].lchild = 0;
tree[i].rchild = 0;
tree[i].weight = 0;
}

for(i = 1; i <= n; i++)
{
tree[i].weight = blanks[i];
}


for(i = n + 1 ; i < n * 2 ; i++)
{
p1 = 0;
p2 = 0;
least1 = maxint;
least2 = maxint;
for(j = 1; j < i; j++)
{
if(tree[j].parent == 0)
{
if(tree[j].weight < least1)
{
least2 = least1;
least1 = tree[j].weight;
p2 = p1;
p1 =j;
}
else
{
if(tree[j].weight < least2)
{
least2 = tree[j].weight;
p2 = j;
}
}
}
}
tree[p1].parent = i;
tree[p2].parent = i;
tree[i].lchild = p1;
tree[i].rchild = p2;
tree[i].weight = tree[p1].weight + tree[p2].weight;
sum += tree[i].weight;
}
tree[2*n - 1].parent = 0;
}

int main()
{
int i,j;
while(cin>>n)
{
sum = 0;
for(i = 1; i <= n; i++)
{
cin>>blanks[i];
}
creattreehufman();
cout<<sum<<endl;
}
return 0;
}
...全文
181 9 打赏 收藏 转发到动态 举报
写回复
用AI写文章
9 条回复
切换为时间正序
请发表友善的回复…
发表回复
vecri 2009-11-17
  • 打赏
  • 举报
回复
做了一下,AC,利用构建哈夫曼树的贪心思想维护一个小顶堆即可


#include <iostream>
#include <queue>
using namespace std;

int N;
int woods[20001];
int main()
{
int i, j;
while (cin >> N)
{
for (i=0; i<N; i++)
cin >> woods[i];

priority_queue<int, vector<int>, greater<int> > q(woods, woods+N);
unsigned int sum = 0;
while (q.size() >= 2)
{
i = q.top();
q.pop();
j = q.top();
q.pop();
sum += i+j;
q.push(i+j);
}
q.pop();
cout << sum << endl;
}
}
qiuzhenguang 2009-11-16
  • 打赏
  • 举报
回复
学习了。。。
caicat 2009-11-14
  • 打赏
  • 举报
回复
[Quote=引用 5 楼 oyzdz1988 的回复:]
楼主的maxint设置的太小了吧    用INT_MAX就可以~
[/Quote]

-------------------
正解
LeonTown 2009-11-14
  • 打赏
  • 举报
回复
先mark
oyzdz1988 2009-11-13
  • 打赏
  • 举报
回复
楼主的maxint设置的太小了吧 用INT_MAX就可以~
oyzdz1988 2009-11-13
  • 打赏
  • 举报
回复
这个题目和原来那个 合并石子 的题目做法是一样的

就是维护一个小顶堆,每次取最小的和第二小的两个元素,然后将两个相加的值放到堆顶,

重新调整下堆,重复上面的做法,一共做 N-1 次即可~
oyzdz1988 2009-11-13
  • 打赏
  • 举报
回复


#include <iostream>
using namespace std;

unsigned int stones[20008];

void adjust(unsigned int n, unsigned int num)
{
unsigned int root, lchild, rchild, min, temp, tag;
while (n*2 <= num)
{
root = stones[n];
lchild = stones[n*2];
rchild = stones[n*2+1];

if (n*2+1 > num)
{
tag = 1;
min = lchild;
}
else
{
tag = lchild < rchild ? 1 : 0;
min = lchild < rchild ? lchild : rchild;
}
if (min < root)
{
if (tag)
{
temp = stones[n];
stones[n] = stones[2*n];
stones[2*n] = temp;
n = 2*n;
}
else
{
temp = stones[n];
stones[n] = stones[2*n+1];
stones[2*n+1] = temp;
n = 2*n+1;
}
}
else
{
break;
}
}
}

void buildHeap(unsigned int n)
{
unsigned int i;
for (i = n/2; i >= 1; i--)
adjust(i, n);
}

int main()
{
unsigned int num, i, total, temp, pre, next;
memset(stones, 0, sizeof(unsigned int)*10008);

cin >> num;
for (i = 1; i <= num; i++)
cin >> stones[i];
if (num == 1)
{
cout << "0" << endl;
return 0;
}

buildHeap(num);
total = 0;
for (i = 0; i < num - 1; i++)
{
pre = stones[1];
temp = stones[1];
stones[1] = stones[num-i];
stones[num-i] = temp;
adjust(1,num-i-1);

next = stones[1];
total += pre + next;
stones[1] = pre + next;
adjust(1,num-i-1);
}

cout << total <<endl;
return 0;
}


whxlcjl 2009-11-13
  • 打赏
  • 举报
回复
全英文,看不懂。。。。ACM有没有中文的题目???
fenix124 2009-11-13
  • 打赏
  • 举报
回复
分太少了

33,007

社区成员

发帖
与我相关
我的任务
社区描述
数据结构与算法相关内容讨论专区
社区管理员
  • 数据结构与算法社区
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
暂无公告

试试用AI创作助手写篇文章吧