贪心算法中一种类型的题(贪心)

这是一组关于贪心算法的问题,旨在寻找最小化损失或最大化收益的最优解。题目涉及作业安排、商品销售计划和木材加工等场景,都需要通过贪心策略,如按扣分或利润降序及截止日期升序排序来确定处理顺序。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

1

Problem Description
Ignatius has just come back school from the 30th ACM/ICPC. Now he has a lot of homework to do. Every teacher gives him a deadline of handing in the homework. If Ignatius hands in the homework after the deadline, the teacher will reduce his score of the final test. And now we assume that doing everyone homework always takes one day. So Ignatius wants you to help him to arrange the order of doing homework to minimize the reduced score.

Input
The input contains several test cases. The first line of the input is a single integer T that is the number of test cases. T test cases follow.
Each test case start with a positive integer N(1<=N<=1000) which indicate the number of homework… Then 2 lines follow. The first line contains N integers that indicate the deadlines of the subjects, and the next line contains N integers that indicate the reduced scores.

Output
For each test case, you should output the smallest total reduced score, one line per test case.

Sample Input
3 3 3 3 3 10 5 1 3 1 3 1 6 2 3 7 1 4 6 4 2 4 3 3 2 1 7 6 5 4

Sample Output
0 3 5
思路
先按照扣分从大到小排序,分数相同则按照截止日期从小到大排序。。
然后按顺序,从截止日期开始往前找没有占用掉的时间。
如果找不到了,则加到罚分里面
代码

#include<stdio.h>
#include<string.h>
#include<algorithm>
using namespace std;
const int MAXN=1010;
struct Node
{
    int d,s;
}node[MAXN];
bool used[10000];
bool cmp(Node a,Node b)
{
    if(a.s==b.s)
    {
        return a.d<b.d;
    }    
    return a.s>b.s;
}        
int main()
{
    int T;
    int n;
    int j;
    scanf("%d",&T);
    while(T--)
    {
        scanf("%d",&n);
        for(int i=0;i<n;i++) scanf("%d",&node[i].d);
        for(int i=0;i<n;i++) scanf("%d",&node[i].s);
        sort(node,node+n,cmp);
        memset(used,false,sizeof(used));
        int ans=0;
        for(int i=0;i<n;i++)
        {
            for(j=node[i].d;j>0;j--)
            {
                if(!used[j])
                {
                    used[j]=true;
                    break;
                }    
            }    
            if(j==0)
              ans+=node[i].s;
        }    
        printf("%d\n",ans);
    }    
    return 0;
}    

2

***.

Problem Description

A supermarket has a set Prod of products on sale. It earns a profit px for each product x∈Prod sold by a deadline dx that is measured as an integral number of time units starting from the moment the sale begins. Each product takes precisely one unit of time for being sold. A selling schedule is an ordered subset of products Sell ≤ Prod such that the selling of each product x∈Sell, according to the ordering of Sell, completes before the deadline dx or just when dx expires. The profit of the selling schedule is Profit(Sell)=Σ x∈Sellpx. An optimal selling schedule is a schedule with a maximum profit.
For example, consider the products Prod={a,b,c,d} with (pa,da)=(50,2), (pb,db)=(10,1), (pc,dc)=(20,2), and (pd,dd)=(30,1). The possible selling schedules are listed in table 1. For instance, the schedule Sell={d,a} shows that the selling of product d starts at time 0 and ends at time 1, while the selling of product a starts at time 1 and ends at time 2. Each of these products is sold by its deadline. Sell is the optimal schedule and its profit is 80. Write a program that reads sets of products from an input text file and computes the profit of an optimal selling schedule for each set of products.

Input

A set of products starts with an integer 0 <= n <= 10000, which is the number of products in the set, and continues with n pairs pi di of integers, 1 <= pi <= 10000 and 1 <= di <= 10000, that designate the profit and the selling deadline of the i-th product. White spaces can occur freely in input. Input data terminate with an end of file and are guaranteed correct.

Output

For each set of products, the program prints on the standard output the profit of an optimal selling schedule for the set. Each result is printed from the beginning of a separate line.

Sample Input

4 50 2 10 1 20 2 30 1

7 20 1 2 1 10 3 100 2 8 2
5 20 50 10

Sample Output

80
185

Hint

The sample input contains two product sets. The first set encodes the products from table 1. The second set is for 7 products. The profit of an optimal schedule for these products is 185

思路
先把所有产品按照利润从大到小排序,然后这个把这个放在截止日期那天卖出,并做好标记,如果截至日期那天已经有其他产品占用了,那么可以把这个产品卖出的时间往前推,直到找到可以卖的那一天并标记好。
假设一个产品a占用了一个日期后,那么如果下次又有一个产品b和产品a的截止日期是相同的,但是那个日期以被占用了,所以就要往前移动1天,那么就可以用并查集进行标记,在a占用了那个日期后,把a的截止日期指向前一个日期,这样的话,可以直接查找到他要占用到哪一个时间。

代码

#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
 using namespace std;
 typedef long long ll;
const int maxn=10005;
int visited[maxn]; //代表第i天是否有卖商品
 struct node{
    int p,d;
};
 bool cmp(node a,node b){
    return a.p>b.p;
}
 int main()
{
    int n;
    while(~scanf("%d",&n)){
        memset(visited,0,sizeof(visited));
        node a[maxn]; //存商品
        for(int i=0;i<n;i++){
            scanf("%d%d",&a[i].p,&a[i].d);
        }
        sort(a,a+n,cmp);
        int sum=0;
        for(int i=0;i<n;i++){
            for(int j=a[i].d;j>=1;j--){ //在截止日期之前卖出就行
                if(visited[j])
                    continue;
                visited[j]=1;
                sum+=a[i].p;
                break;
            }
        }
        printf("%d\n",sum);
    }
    return 0;
}

3

Description

Ignatius has just come back school from the 30th ACM/ICPC. Now he has a lot of homework to do. Every teacher gives him a deadline of handing in the homework. If Ignatius hands in the homework after the deadline, the teacher will reduce his score of the final test. And now we assume that doing everyone homework always takes one day. So Ignatius wants you to help him to arrange the order of doing homework to minimize the reduced score.

Input

The input contains several test cases. The first line of the input is a single integer T that is the number of test cases. T test cases follow.
Each test case start with a positive integer N(1<=N<=1000) which indicate the number of homework… Then 2 lines follow. The first line contains N integers that indicate the deadlines of the subjects, and the next line contains N integers that indicate the reduced scores.

Output

For each test case, you should output the smallest total reduced score, one line per test case.

Sample Input

3
3
3 3 3
10 5 1
3
1 3 1
6 2 3
7
1 4 6 4 2 4 3
3 2 1 7 6 5 4

Sample Output
0

3
5

代码

#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
const int MAXN=1010;
struct Node
{
    int d,s;
}node[MAXN];
bool used[10000];
bool cmp(Node a,Node b)
{
    if(a.s==b.s)
    {
        return a.d<b.d;
    }    
    return a.s>b.s;
}        
int main()
{
    int T;
    int n;
    int j;
    scanf("%d",&T);
    while(T--)
    {
        scanf("%d",&n);
        for(int i=0;i<n;i++) scanf("%d",&node[i].d);
        for(int i=0;i<n;i++) scanf("%d",&node[i].s);
        sort(node,node+n,cmp);
        memset(used,false,sizeof(used));
        int ans=0;
        for(int i=0;i<n;i++)
        {
            for(j=node[i].d;j>0;j--)
            {
                if(!used[j])
                {
                    used[j]=true;
                    break;
                }    
            }    
            if(j==0)
              ans+=node[i].s;
        }    
        printf("%d\n",ans);
    }    
    return 0;
}    

4

***.
Problem Description

There is a pile of n wooden sticks. The length and weight of each stick are known in advance. The sticks are to be processed by a woodworking machine in one by one fashion. It needs some time, called setup time, for the machine to prepare processing a stick. The setup times are associated with cleaning operations and changing tools and shapes in the machine. The setup times of the woodworking machine are given as follows:

(a) The setup time for the first wooden stick is 1 minute.
(b) Right after processing a stick of length l and weight w , the machine will need no setup time for a stick of length l’ and weight w’ if l<=l’ and w<=w’. Otherwise, it will need 1 minute for setup.

You are to find the minimum setup time to process a given pile of n wooden sticks. For example, if you have five sticks whose pairs of length and weight are (4,9), (5,2), (2,1), (3,5), and (1,4), then the minimum setup time should be 2 minutes since there is a sequence of pairs (1,4), (3,5), (4,9), (2,1), (5,2).

Input

The input consists of T test cases. The number of test cases (T) is given in the first line of the input file. Each test case consists of two lines: The first line has an integer n , 1<=n<=5000, that represents the number of wooden sticks in the test case, and the second line contains n 2 positive integers l1, w1, l2, w2, …, ln, wn, each of magnitude at most 10000 , where li and wi are the length and weight of the i th wooden stick, respectively. The 2n integers are delimited by one or more spaces.

Output

The output should contain the minimum setup time in minutes, one per line.

Sample Input

3
5
4 9 5 2 2 1 3 5 1 4
3
2 2 1 1 2 2
3
1 3 2 2 3 1

Sample Output

2
1
3

题意:加工木材,如果后一个长度和重量都大于等于前一个,那么就不需要调器,否则需要重新调机器,时间要加一分钟,输出需要的最少时间。

思路:就是先按长度或者重量从小到大排序,然后再按另一种进行找需要调机器的最少次数。

代码:

#include<cstdio>
#include<algorithm>
using namespace std;
struct note
{
    int l,w;
} e[10100];
bool  cmp(note x,note y)
{
    if(x.l==y.l)
        return x.w<y.w; //当长度相同时按重量排序,不写这个会出错
    else
        return x.l<y.l;
}
int main()
{
    int n;
    scanf("%d",&n);
    while(n--)
    {
        int m;
        scanf("%d",&m);
        int i,j;
        for(i=0; i<m; i++)
            scanf("%d%d",&e[i].l,&e[i].w);
        sort(e,e+m,cmp);           //用sort按长度排序
        int book[10100]={0},sum=0;
        for(i=0; i<m; i++)
        {
 
            if(book[i]) continue;   //如果已经用过了跳过
            int maxx=e[i].w;
            for(j=i+1; j<m; j++)    //找后面比前一个重量大的,
                                    //因为长度已经排好序了可以不用管。
            {
                if(!book[j]&&maxx<=e[j].w) 
                {
                    book[j]=1;
                    maxx=e[j].w;    //将找到的最新的重量赋给maxx
                }
            }
            sum++;
        }
        printf("%d\n",sum);  
    }
    return 0;
}

以上四道题都属于贪心算法题的同种类型,可以比较来看看。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值