寒假作业第二组P&&Q&&R题解

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了寒假作业第二组P&&Q&&R题解相关的知识,希望对你有一定的参考价值。

P的题意是有M份作业,这些作业有不同的截止日期,超过截止日期完成,不同的作业有不同的罚分,求如何完成罚分最低。

首先,从截止日期最长的那个作业到截止日期,这些天数是固定的,所做的就是把这些作业填进这些天。很明显的贪心,把作业按从大到小罚分排序,罚分截止日期越近的放在前面,然后通过枚举把作业往时间轴里放,知道这些天数被填满。

 1 #include <iostream>
 2 #include <algorithm>
 3 #include <cstdio>
 4 #include <map>
 5 #include <string>
 6 #include <string.h>
 7 #include <queue>
 8 #include <vector>
 9 using namespace std;
10 struct subject{
11       int point;
12       int time;
13 };
14 int compare(struct subject a,struct subject b)
15 {
16         if(a.point!=b.point)
17         {
18                 if(a.point>b.point)
19                     return 1;
20                 else return 0;
21         }
22         else {
23                 if(a.time<b.time)
24                         return 1;
25                 else return 0;
26         }
27 }
28 int main()
29 {
30     int n;
31     scanf("%d",&n);
32     for(int i=0;i<n;i++)
33     {
34         int m;
35         int sum=0;
36         int flag[1000]={0};
37         struct subject sb[2000];
38         int a[10000]={0};
39         int b[10000]={0};
40         scanf("%d",&m);
41         for(int j=0;j<m;j++)
42         {
43             scanf("%d",&a[j]);
44             sb[j].time=a[j];
45         }
46         for(int h=0;h<m;h++)
47         {
48                 scanf("%d",&b[h]);
49              sb[h].point=b[h];
50         }
51         sort(sb,sb+m,compare);
52         for(int g=0;g<m;g++)
53         {
54                for(int j=sb[g].time;j>=0;j--)
55                {
56                        if(!flag[j]&&j)
57                        {
58                                flag[j]=1;
59                                break;
60                        }
61                        if(!j)
62                       sum+=sb[g].point;
63                }
64         }
65         printf("%d\n",sum);
66     }
67     return 0;
68 }

Q的题意其实跟DOTA没啥关系,可以理解成回合制游戏,只不过每次都是敌人先攻击你,你的血量无限,不过你每次只能打对方一点血,对方有DFS(每次攻击你掉的血)和HP(血量)两个特征,求把他们打死,你消耗的最少血量。既然是贪心,就要排序,按DFS排还是按HP排呢,都不是,因为你优先要打的是,HP低&&攻击力强的敌人,所以应该优先打DFS/HP大的敌人。

#include <iostream>
#include <algorithm>
#include <cstdio>
#include <map>
#include <string>
#include <string.h>
#include <queue>
#include <vector>
using namespace std;
struct hero{
  int dps;
  int hp;
};
int compare(struct hero a,struct hero b)
{
        if((a.dps*1.0/a.hp)>(b.dps*1.0/b.hp))
                return 1;
        else return 0;
}
int main()
{
    int n;
    while(scanf("%d",&n)!=EOF)
    {
        int sum=0;
        struct hero a[1000];
        for(int i=0;i<n;i++)
        scanf("%d%d",&a[i].dps,&a[i].hp);
        sort(a,a+n,compare);
        for(int j=0;j<n;j++)
        {
             for(int h=j;h<n;h++)
             {
                sum+=a[h].dps*(a[j].hp);
             }
        }
        printf("%d\n",sum);
    }
    return 0;
}

R题,题意很简单,有n个机器,m个任务,每个机器和任务都对应着 time和level两个量,只有机器的时间和等级都大于等于任务时,才能完成任务,求完成任务的最大数量,多解考虑利润最多的情况,利润是任务的时间*500+等级*2;

因为任务的时间权重很高,所以可以直接忽略利润这个东西。

我本来的想法是,从最简单地任务开始(简单就是时间少且等级低,首要看时间)每个任务,都从最烂的机器(烂机器就是时间少,等级低)开始匹配,匹配上的机器用flag标记,结果超时了,确实,这么做太暴力,因为任务的简单和机器的烂是有联系的,特别是当他们被排好顺序的时候。最后借鉴了别人的方法。从最难的任务开始,然后先挑出一部分时间上满足的机器,然后再看等级。再下一个任务,因为排好序所以比上一个任务简单,可以继续用到上一次被挑出来的机器,还可以继续挑选机器,节省了时间。

#include <iostream>
#include <algorithm>
#include <cstdio>
#include <map>
#include <string>
#include <string.h>
#include <queue>
#include <vector>
using namespace std;
struct com{
     int time;
     int level;
};
int compare(struct com a,struct com b)
{
        if(a.time!=b.time)
        {
                if(a.time>b.time)
                    return 1;
                else return 0;
        }
        else return a.level>b.level;
}
int main()
{
    int n,m;
    while(scanf("%d%d",&n,&m)!=EOF)
    {
        struct com mac[100010];
        struct com task[100010];
        int flag[100010]={0};
        int cnt=0;
        long long sum=0;
        for(int i=0;i<n;i++)
           scanf("%d%d",&mac[i].time,&mac[i].level);
        for(int j=0;j<m;j++)
           scanf("%d%d",&task[j].time,&task[j].level);
        sort(mac,mac+n,compare);
        sort(task,task+m,compare);
        for(int i=0,j=0;i<m;i++)
        {
                while(j<n&&mac[j].time>=task[i].time)
                {
                        flag[mac[j].level]++;
                        j++;
                }
                for(int h=task[i].level;h<=100;h++)
                {
                        if(flag[h])
                        {
                               flag[h]--;
                               cnt++;
                               sum+=500*task[i].time+2*task[i].level;
                               break;
                        }
                }
        }
        printf("%d %lld\n",cnt,sum);
    }
    return 0;
}

 

以上是关于寒假作业第二组P&&Q&&R题解的主要内容,如果未能解决你的问题,请参考以下文章

第二次作业

第二次作业

第二次作业

第二次作业

第二次作业——交换两个整形变量的数值

[NWPU2016][寒假作业][正常版第二组]U