湖北中醫藥大學2019暑期練習賽(四)

A - Saruman’s Army POJ - 3069

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.

題目大意

在一條直線上,有n個點。從這n個點中選擇若干個,給他們加上標記。對於每一個點,其距離爲R以內的區域裏必須有一個被標記的點。問至少要有多少點被加上標記。

解題思路

先進行從小到大的排序,從最左邊的開始考慮。對於這個點,到距其R以內的區域必須要有帶有標記的點。帶有標記的點一定在其右側(包含這個點本身)。給從最左邊開始,距離爲R以內的最遠的點加上標記,儘可能的覆蓋更靠右邊的點。對於添加了標記的點右側相距超過R的下一個點,採用同樣的方法找到最右側R距離以內最遠的點添加標記。在所有點都被覆蓋之前不斷重複這一過程。

源代碼

#include <algorithm>
#include <iostream>

using namespace std;
int main()
{
    int n,len,count;
    int a[1005];
    while(cin>>len>>n&&(len!=-1&&n!=-1))
    {
        for(int i=0;i<n;i++)
        {
            cin>>a[i];
        }
        sort(a,a+n);
        count=0;
        for(int i=0;i<n;i++)
        {
            for(int j=i;j<n;j++)//找到中心點
            {
                if(a[i]+len<a[j])
                {
                    i=j-1;
                    break;
                }
            }
            if(a[i]+len>=a[n-1])//所有點都已經覆蓋了
            {
                count++;
                break;
            }

            for(int j=i;j<n;j++)//找到第一個未覆蓋的點,下一次循環從這裏開始
            {
                if(a[i]+len<a[j])
                {
                    i=j-1;
                    break;
                }
            }
            count++;
        }
        cout<<count<<endl;

    }
    return 0;
}

B - Fence Repair POJ - 3253

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,求最小費用

解題思路

利用哈夫曼的思想,要使總費用最小,那麼每次只選取最小長度的兩塊木板相加,再把這些和累加到總費用中即可。用優先隊列處理。
priority_queue q;      //通過操作,按照元素從大到小的順序出隊
priority_queue<int,vector, greater > q;   //通過操作,按照元素從小到大的順序出隊

源代碼

#include <cstdio>
#include <queue>
#include <vector>
#include <iostream>
using namespace std;
int main()
{
	int n;
	long long temp,a,b,mincost;
	while(~scanf("%d",&n))
	{
		priority_queue<int, vector<int>, greater<int> > Q;

		while(!Q.empty())
			Q.pop();

		for(int i = 1; i <= n; i++)
		{
			scanf("%I64d",&temp);
			Q.push(temp);
		}

		mincost = 0;

		while(Q.size() > 1)
		{
			a = Q.top();
			Q.pop();
			b = Q.top();
			Q.pop();
			Q.push(a+b);
			mincost +=a+b;
		}
		printf("%I64d\n",mincost);
	}
	return 0;
}
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章