[2011山东省第二届ACM大学生程序设计竞赛]——Mathmen

Mathmen

Time Limit: 1000ms Memory limit: 65536K 有疑问?点这里^_^

题目:http://acm.sdut.edu.cn/sdutoj/problem.php?action=showproblem&problemid=2168

题目描述
Mathmen love mathematics, and they live on the number line. All the mathmen spend all their time on solving mathematical problems and proving theorems. Like humen beings, mathmen don't live in the same country there are n mathmen countries on difierent positions of the number line (country i lives at position xi (one point on the number line), and xi < xi + 1 for all 1 <= i <= n - 1). Mathmen in difierent countries are good at difierent areas of mathematics. For example, mathmen living in country 1 are good at geometry, while mathmen living in country 2 are experts on algebra.
Lately, all the mathmen nations have collaborated on a huge problem, which involves all areas of mathematics, and each mathmen country is responsible for solving the part they are good at. After hours of work (they are really good at mathematics, and no problem would cost them more than one day to solve), they all finish their jobs. Now, they need to collect the result in every mathmen country, and combine them together to create the solution to the huge problem. So they decide to let one mathman collect all the results and send it to one country, where all the work will be merged.
As mathmen are devoted to solving mathematical problems, their legs has become very weak after millions of years of evolution. Therefore, they have to ride mathships to travel on the number line. Their are M types of mathships, each of which has a limit of traveling distance and a cost of IQ (yes, you need to be very brave to take mathships, you would never be able to get back the lost IQ).
There are two seasons in the mathmen world Positive and Negative. Now it is Positive, so all the mathships travels on the number line from left to right. Therefore, one man from country 1 must be selected as the volunteer to collect the results in every country and send to to country n.
There is at least one mathship of each type in every country. So, after picking the results from country 1, the volunteer needs to select one mathship with a limit of traveling distance at least the distance between country 1 and country 2 (the distance is x2 - x1), and ride it from country 1 to country 2.
Meahwhile, this trip will cost him the corresponding amount of IQ. Then, he picks the result from country 2, choose another suitable mathship (the old mathship will be maintained in country 2, and can not continue to be used), and ride it to country 3, and lose some IQ. He will repeat this process, until he reaches country n.
Mathmen care about their IQ a lot, so the volunteer wants to minimize the total cost of his IQ. Could you please write program to help him select the right mathships to take?
输入
The input contains multiple test cases. The first line of the input is an integer C, indicating the number of test cases in the input.
Each test case begins with a line containing two integers, n (2 <= n <= 10000) and m (1 <= m <= 100000), which is the number of mathmen countries and the number of mathship types. The next line contains n integers, ranging from -10^9to10^9(inclusive), indicating the positions of the mathmen countries. Then, m lines follows, each containing two non-negative integers no more than 2*109, which are the limit of traveling distance and the cost of IQ.
输出
For each test case, output one line containing the minimum cost of IQ. If the volunteer can never reach country n, output "Impossible" (without quotation marks).
示例输入
2
3 3
0 3 10
1 0
6 1
10 10
2 1
0 1000
100 0
示例输出
11

Impossible


这道题,当时比赛时,我们唯一一个没有翻译的题目。。。其实这道题很简单,贪心即可A。

先说一下题意吧:一个人要从第一个城市到达最后一个城市,每个城市都有m种交通工具。

给出每个交通工具加满油后最多行驶的距离和油量,求从第一个城市到最后一个城市耗油最少为多少?

(上述的油啊,什么的是我加的,显得更好理解一些)。如果无法到达则输出Imposible

注意以下几点:

①给出的是城市的坐标,并以从小到大给出。

②每个城市都有m种交通工具,因此一个交通工具可以重复用。

③假设一个交通工具可以走10公里,耗油为4,即使城市间距离不足10公里,耗油量依旧按照4计算。

④求最小油耗


解法:这道题,先求出两个相邻城市间的距离,并按照由大到小排序。再将每个交通工具所能到达的距离由大到小排序。可以先判断 交通工具所能到达的最大距离是否大于相邻城市最大间距。若小于则Imposible

如果大于等于,则可以到达最后一个城市。

从最大的城市间距开始向后遍历,将能到达此间距的交通工具扔进队列中。

这里的队列用优先队列,优先级根据 油量,耗油量少的排在队列首部。

这里用一个例子来说这个循环:

这里有两段路程,第一段路程距离为10,第二段路程距离为4.

交通工具有4个:

一号  距离 15 耗油 10

二号  距离 10 耗油  4

三号  距离 7   耗油  6

四号  距离 3   耗油  1

先判断第一段路程,

这里有两个交通工具可以到达,一号工具和二号工具,

将一号工具和二号工具扔进队列,因为优先队列,会根据油量排序,位于顶部的是二号。

用一个sum值记录总耗油数,sum+=4(初始值为0)

然后判断第二段路程,距离为4,此时发现一号和二号依旧满足题意。

(这里就是一个类似于搜索中剪枝,我们没有必要每次都从第一个交通工具判断,路程是越来越短的,

所以,前面能符合要求的交通工具在后面一定会符合要求,这几个交通工具没有必要退队列。只需要向队列里面加。)

三号工具也满足,四号不满足,于是把三号工具也扔进队列。

队列根据油量排序,位于首部的依旧是2号,sum+=4

(这也说明了,并非你到的路程段,耗油就少。。)

最后可以输出sum。

PS:最后要说明一点,数据类型的存储要用Long long。否则WA。。。

还有一点,对于大数据量的输入,最好用scanf,我用cin耗时510MS,用scanf耗时210MS。。差别还是挺大的。

long long scanf用 %lld


#include <stdio.h>
#include <algorithm>
#include <queue>
using namespace std;
struct Tool
{
    long long distance;
    long long qi;
    friend bool operator <(Tool a,Tool b)
    {
        return a.qi>b.qi;
    }
}tool[100011];
long long n,m,stop[10011];

// 求最小QI
void calculate(void)
{
    int i,j;
    long long sum;
    priority_queue <Tool> q;
    while(!q.empty())   {q.pop();}

    sum=j=0;
    for(i=0;i<n-1;++i)
    {
        while(stop[i]<=tool[j].distance && j<m)
        {
            q.push(tool[j]);
            ++j;
        }
        sum+=q.top().qi;
    }
    printf("%lld\n",sum);
}
// tool和stop的比较函数
bool cmp_s(int a,int b)
{
    return a>b;
}
bool cmp_t(Tool a,Tool b)
{
    if(a.distance==b.distance)  return a.qi<b.qi;
    return a.distance>b.distance;
}
int main()
{
    int i,test;
    
    scanf("%d",&test);
    while(test--)
    {
        scanf("%d%d",&n,&m);
/*      
        // 输入既可用这种也可以用下面那种,这种少了一个循环可以减少20MS
        long long temp;
        scanf("%lld",&temp);
        for(i=0;i<n-1;++i)
        {
            scanf("%lld",&stop[i]);
            stop[i]-=temp;
            temp=stop[i]+temp;
        }
*/
        for(i=0;i<n;++i)    scanf("%lld",&stop[i]);  
        for(i=0;i<n-1;++i)  stop[i]=stop[i+1]-stop[i];  
        // tool数组存工具的可行驶距离和qi值
        for(i=0;i<m;++i)    scanf("%lld%lld",&tool[i].distance,&tool[i].qi);
        // stop和tool均按从大到小排序
        sort(stop,stop+n-1,cmp_s);
        sort(tool,tool+m,cmp_t);


        if( stop[0]>tool[0].distance )   printf("Impossible\n");
        else    calculate();
    }
    return 0;
}



   

你可能感兴趣的:(ACM,贪心,山东省赛,Mathmen)