Beginner greedy algorithm

Posted by cauchyResidue on Wed, 09 Feb 2022 00:13:11 +0100

P2240 [deep foundation 12. Example 1] some knapsack problems

Title Description
Ali Baba walked into a treasure hole full of treasures. There are N(N ≤ 100) piles of gold coins in the treasure cave. The total weight and total value of the I pile of gold coins are MI and VI (1 < = MI, VI < = 100). Alibaba has a backpack with a weight of T(T ≤ 1000), but there is not necessarily a way to put all the gold coins in it. He wanted to pack as many gold coins as possible. All gold coins can be divided at will, and the weight value ratio (i.e. unit price) of the divided gold coins remains unchanged. How much gold coins can Alibaba take at most?

Input format
The first line contains two integers N,T.

Next N lines, each with two integers mi,vi.

Output format
A real number represents the answer and outputs two decimal places

input

4 50
10 60
20 100
30 120
15 45

output

240.00

My idea:

Because I've been learning greedy algorithm recently, I know it's greedy, but according to the meaning of the topic, for maximum value, you can also know one or two.

Because all gold coins can be divided at will, and the weight value ratio of the divided gold coins remains unchanged, we try to get as many gold coins with high weight value ratio as possible, so we use the sort function to arrange quickly, so as to get high gold coins conveniently.

Therefore, a greedy algorithm is generated: in the optional gold coin pile, the gold coin with high value is selected each time, followed by the gold coin with high value, and so on.

Here, I use pair type to store data. Of course, I can also use structure; And use pair's sort fast platoon. ( See my other article for the specific implementation method)

Reminder: learn to use it now.

Note: the output is a real number, so use decimal division instead of integer division. Don't be confused by the surface of the sample.

The code is as follows:

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

typedef pair<int ,int > P;
int n,t;

//Sort method custom collation: sort in descending order.
bool cmp(P a,P b){
	return a.second * 1.0/a.first > b.second * 1.0/b.first;
}

int main()
{
	cin >> n >> t;
	P *p = new P[n + 1];
	for (int i = 1;i <= n;i ++){
		cin >> p[i].first >> p[i].second;
	}
	sort(p + 1,p + n + 1,cmp);
	double ans = 0;
	for (int i = 1;i <= n;i ++){
		if (p[i].first <= t){ //Fill up a pile before it's full.
			ans += p[i].second;
			t -= p[i].first;
		} else {
			ans += t * p[i].second * 1.0 / p[i].first;
			break;
		}
	}
	printf("%.2lf",ans);
	return 0;
}

The idea of the boss:

Sort according to the cost performance from large to small, and then pack them one by one until they can't fit.

Open a structure gold to store m, VM and V, and use custom comparison function and sort to sort.

The code is as follows:

#include <bits/stdc++.h>
using namespace std;

struct gold{
	int m,v;//m is the weight,v is the money.
};
//Custom quick scheduling rules
bool cmp(gold a,gold b){
	return a.v*b.m>b.v*a.m;
}
//Read quickly and mark the inline inline function.
inline int read(){
	char c;
	bool flag=false;
	while((c=getchar())<'0'||c>'9')
	    if(c=='-') flag=true;
	int res=c-'0';
	while((c=getchar())>='0'&&c<='9')
	    res=(res<<3)+(res<<1)+c-'0';
	return flag? -res:res;
}

gold a[110];

int main(){
	int n=read(),t=read();
	double coin=0;
	for(int i=0;i<n;i++){
		a[i].m=read();
		a[i].v=read();
	}
	sort(a,a+n,cmp);
	int i;
	for(i=0;i<n;i++){
		if(t<a[i].m) break;//Here, the operation is carried out outside the loop.
		coin+=a[i].v;
		t-=a[i].m;
	}
	if(i<n) coin+=1.0*t*a[i].v/a[i].m;
	printf("%.2lf",coin);
	return 0;
}

Summary:

1. read

Fast reading: faster than cin and scanf, it is said to be 1ms faster.

Read in a case of int:

inline int read(){
	char c;
	bool flag=false;	//Determine whether there is a negative sign.
	while((c=getchar())<'0'||c>'9')	//Exclude miscellaneous items (i.e. values that are not numbers, such as white space characters)
	    if(c=='-') 
	    	flag=true;
	int res=c-'0';	//Because after reading in the number and exiting the loop, c is a number, not miscellaneous.
	while((c=getchar()) >= '0' && c <= '9')
	    res=(res<<3)+(res<<1)+c-'0';	//Carry through bit operation to improve efficiency, rather than multiplying by 10.
	return flag? -res:res;;	//Through the ternary operator
}

(res<<3) + (res<<1) == (res * 8 + res * 2)
Move left: res < < n; Multiply by 2 to the nth power.
Move right: res > > n; Divide by 2 to the nth power.

Learn more about fast reading and fast losing ( 👈 (portal)

2. Comparison of ternary operator and if else

Readability: the ternary operator is better than if else.
Because the binocular operator is concise and easy to read.

Efficiency difference
Without compiler optimization, the ternary operator is slower than if else, because the ternary operator also uses additional temporary variables, which operate first and then assign values. If else is a direct assignment, and there is no operation, so the speed will be very fast;

temp: Temporary variable,Or it is a variable that passes parameter assignment.
temp = flag ? -res:res; 
temp = read();	//int read() {return flag ? -res:res; }

But now the compiler will optimize these. The optimized assembly code is the same, just like i + + and + + i. The compiled and optimized assembly code is the same.
i + +: assign value first and then calculate.
++i: operation first and then assignment.

Complete proof process ( 👈 (portal)

3. Avoid the operation of division. Return A.V * B.M > B.V * a.m;

It should have been A.V / a.m > B.V / B.M;

prove:
∵ x ÷ y = z stands for x = z × y,
∴ a.v ÷ a.m > b.v ÷ b.m
 a.v > b.v ÷ b.m × a.m
 a.v × b.m > b.v × a.m
In this way, floating point numbers can be avoided and accuracy can be increased.

4. Code interpretation if (I < n) coin + = 1.0 * t * a [i] v / a[i]. m;

*1.0 is decimal division* t is that this pile of gold coins cannot be filled, so multiply by t;
If I < n, fill the remaining capacity (t) of the backpack with the i-th gold coin, plus the price of the gold coin (t) × Unit price (a[i].v/a[i].m)).

Topics: greedy algorithm