贪心:Fence Repair、Saruman's Army

Fence Repair

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).

中文翻译:
围栏维修
农夫约翰想修一小段牧场周围的篱笆。他测量了栅栏,发现他需要n(1≤n≤20000)块木板,每块木板都有一些整数长度的li(1≤li≤50000)单位。然后他买了一块长木板,长度刚好能锯进n块木板(即,木板的长度是长度的总和li)。fj忽略了“切口”,即锯切时锯屑所损失的额外长度;你也应该忽略它。
福建悲哀地意识到,他没有一个锯与削减木材,所以他大摇大摆地到农民唐的农场与这个长板,礼貌地问他是否可以借用一把锯。
农民唐,一个秘密资本家,不借给FJ一把锯子,而是提出向农民约翰收取木板上每一个N-1切口的费用。砍一块木头的费用正好等于它的长度。切割一块长21的木板要花21美分。
农夫唐让农夫约翰决定切割木板的顺序和地点。帮助农场主约翰确定他能花多少钱来制作木板福建知道,他可以削减董事会在不同的顺序,这将导致不同的费用,因为产生的中间木板是不同的长度。
输入
第1行:一个整数n,木板的数量
第2行…n+1:每行包含一个整数,用于描述所需木板的长度
输出
第1行:一个整数:他必须花费最少的钱来进行n-1次削减
暗示
他想把一块21长的木板切成8、5和8长的几块。
原来的棋盘是8+5+8=21。第一次切割要花21英镑,应该用来把木板切成13和8块。第二次削减将花费13,并应用于削减13成8和5。这将花费21+13=34。如果把21分为16分和5分,第二次削减将花费16分,总共37分(超过34分)。
CODE:

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

int main()
{
    priority_queue<int,vector<int>,greater<int> > q;
    int n,m,i,t;
    cin>>n;
    for(i=0;i<n;i++)
        cin>>m,q.push(m);
    long long sum=0;
    while(q.size()>1)
    {
        m=q.top();
        q.pop();
        t=q.top();
        q.pop();
        sum+=(m+t);
        q.push(m+t);
    }
    cout<<sum<<endl;
    return 0;
}

知识补充:

C++优先队列的基本使用方法
在优先队列中,优先级高的元素先出队列。
标准库默认使用元素类型的<操作符来确定它们之间的优先级关系。
一、
大多数时候,我们再进行宽度优先搜索时,队列元素往往不只一个,比如一个元素可能包含节点、权重,我们是按照节点大小排序还是按照权重大小排序,或者是先按照权重比较大小,如果权重相同再按照节点比较大小,这就需要用户自定义比较函数来进行优先队列的排序。
  一般来说,自定义comp都是类或者结构体,里面重载运算符来进行比较,比如对于二元组(x,y) ,要根据x 排序,则可这样定义comp

struct tmp
{
    int x,y;
};
struct comp
{
    int x;
    bool operator()(tmp &a,tmp &b)
    {
        return a.x<b.x;
    }
};
struct tmp
{
    int x,y;
    bool operator < (const tmp &a,const tmp &b)
    {
        if(a.x==b.x)
        {
            return a.y<b.y;
        }
        else
        {
            return a.x<b.x;
        }
    }
};

二、

priority_queue<type,vector<type>,comp>Q;
priority_queue<int,vector<int>,greater<int> > q;

第一个参数type是数据类型
第二个是容器类型,STL默认容器是vector
第三comp个是比较函数,如果没有此参数,默认大根堆,即降序排列

系统提供升序比较函数greater< type >,降序比较函数less< type>

Saruman’s Army

Saruman the White must lead his army along a straight path from Isengard to Helm’s Deep. To keep track of his forces, Saruman distributes seeing stones, known as palantirs, among the troops. Each palantir has a maximum effective range of R units, and must be carried by some troop in the army (i.e., palantirs are not allowed to “free float” in mid-air). Help Saruman take control of Middle Earth by determining the minimum number of palantirs needed for Saruman to ensure that each of his minions is within R units of some palantir.

Input
The input test file will contain multiple cases. Each test case begins with a single line containing an integer R, the maximum effective range of all palantirs (where 0 ≤ R ≤ 1000), and an integer n, the number of troops in Saruman’s army (where 1 ≤ n ≤ 1000). The next line contains n integers, indicating the positions x1, …, xn of each troop (where 0 ≤ xi ≤ 1000). The end-of-file is marked by a test case with R = n = −1.

Output
For each test case, print a single integer indicating the minimum number of palantirs needed.

Sample Input

0 3
10 20 20
10 7
70 30 1 7 15 20 50
-1 -1

Sample Output

2
4

Hint
In the first test case, Saruman may place a palantir at positions 10 and 20. Here, note that a single palantir with range 0 can cover both of the troops at position 20.

In the second test case, Saruman can place palantirs at position 7 (covering troops at 1, 7, and 15), position 20 (covering positions 20 and 30), position 50, and position 70. Here, note that palantirs must be distributed among troops and are not allowed to “free float.” Thus, Saruman cannot place a palantir at position 60 to cover the troops at positions 50 and 70.

中文翻译:
白人萨鲁曼必须带领他的军队沿着一条从伊辛格到赫尔姆湾的直线行进。为了追踪他的部队,萨鲁曼在部队中分发了一种叫做帕兰提斯的石头。每个PARANTR具有R单位的最大有效范围,并且必须由军队中的一些部队携带(也就是说,PalutRS不允许“自由漂浮”在空中)。帮助萨鲁曼控制中土,确定萨鲁曼所需的最少宫殿数量,以确保他的每一个仆从都在某个宫殿的R单位内。
输入
输入测试文件将包含多个案例。每个测试用例从一个包含整数R的单行开始,所有PalutRs的最大有效范围(其中0个小于r 1000),和一个整数n,SARUMAN军队中的部队数量(其中1个小于N 1000)。下一行包含n个整数,指示每个部队的位置x1,…,xn(其中0个小于Xi的下限为1000)。文件结尾由一个r=n=-1的测试用例标记。
输出
对于每个测试用例,打印一个表示所需最少palantir数的整数。
暗示
在第一个测试用例中,saruman可以在位置10和20放置一个palantir。这里,请注意,一个范围为0的帕兰蒂尔可以覆盖20号阵地的两个部队。
在第二个测试用例中,saruman可以将palantirs放置在位置7(覆盖1、7和15处的部队)、位置20(覆盖20和30处的部队)、位置50和位置70。在这里,请注意,圣骑士必须在部队中分配,并且不允许“自由浮动”。因此,萨鲁曼不能将圣骑士安置在60号位置,以覆盖50号和70号位置的部队。
CODE:

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

int main()
{
    int r,n;
    while(cin>>r>>n)
    {
        if(r==-1&&n==-1)
            break;
        int i,d;
        int a[1100];
        for(i=1; i<=n; i++)
            cin>>a[i];
        sort(a+1,a+1+n);
        int re=0;
        for(i=1; i<=n; i++)
        {
            d=a[i]+r;
            while(a[i+1]<=d&&i<=n)
                i++;
            d=a[i]+r;
            while(a[i+1]<=d&&i<=n)
                i++;
            re++;

        }
        cout<<re<<endl;
    }
    return 0;
}

猜你喜欢

转载自blog.csdn.net/weixin_44350170/article/details/102846579
今日推荐