Algorithms and Analysis Learning Topic Records - Greedy Method

Table of contents

10 Backpack Questions

Arbitrary knapsack problem

counting game

order of service

Merge fruit

budget for village-to-village projects

shortest distance

Activity sequencing problem


10 Backpack Questions

#include<iostream>
using namespace std;
struct items {
	double amount;
	double price;
	double weight;
	string name;
};
void kp(struct items a[], int i, int j) {
	if (i > j)
		return;
	double temp = a[i].price / a[i].weight;
	items tmp = a[i];
	int l = i;
	int r = j;
	while (i != j) {
		while (i < j && a[j].price / a[j].weight <= temp)
		{
			j--;
		}
		a[i] = a[j];
		while (i < j && a[i].price / a[i].weight >= temp)
		{
			i++;
		}
		a[j] = a[i];
	}
	a[i] = tmp;
	kp(a, l, i - 1);
	kp(a, i + 1, r);
}


void Knap(struct items a[], int vmax, int n) {
	int maxprice = 0;
	int* getitem = new int[n];
	for (int i = 0; i < n; i++) {
		if (vmax >= a[i].weight) {
			vmax -= a[i].weight;
			maxprice += a[i].price;
			getitem[i] = 1;
		}
	}
	cout << "物品价格\t物品重量\t物品名字" << endl;
	for (int j = 0; j < n; j++) {
		if (getitem[j] == 1)
			cout << a[j].price << "\t\t" << a[j].weight << "\t\t" << a[j].name << endl;
	}
	cout << "最大化价值:" << maxprice << endl << "剩余背包容量:" << vmax << endl;
	delete[] getitem;
}
void main() {
	int n, maxv;
	cout << "请输入物品种类数量:";
	cin >> n;
	cout << "请输入背包承重:";
	cin >> maxv;
	items* good = new items[n];
	cout << "请依次输入物品价格、重量、名字" << endl;
	for (int i = 0; i < n; i++) {
		cin  >> good[i].price >> good[i].weight >> good[i].name;
	}
	kp(good, 0, n - 1);
	cout << "物品价格\t物品重量\t物品名字" << endl;
	for (int i = 0; i < n; i++) {
		cout << good[i].price << "\t\t" << good[i].weight << "\t\t" << good[i].name << endl;
	}
	cout << endl << endl << "--------------------拿取物品--------------------" << endl;
	Knap(good, maxv, n);
	delete[] good;
}

Arbitrary knapsack problem

#include<iostream>
using namespace std;
struct items {
	double amount;
	double price;
	double weight;
	string name;
};
void kp(struct items a[], int i, int j) {
	if (i > j)
		return;
	double temp = a[i].price / a[i].weight;
	items tmp = a[i];
	int l = i;
	int r = j;
	while (i != j) {
		while (i < j && a[j].price / a[j].weight <= temp)
		{
			j--;
		}
		a[i] = a[j];
		while (i < j && a[i].price / a[i].weight >= temp)
		{
			i++;
		}
		a[j] = a[i];
	}
	a[i] = tmp;
	kp(a, l, i - 1);
	kp(a, i + 1, r);
}


void Knap(struct items a[], int vmax, int n) {
	int maxprice = 0;
	int i = 0;
	while (a[i].weight < vmax) {
		vmax -= a[i].weight;
		maxprice += a[i].price;
		i++;
	}
	if (vmax > 0) {
		maxprice += vmax / a[i].weight * a[i].price;
	}
	cout << "物品数量\t物品名字" << endl;
	for (int j = 0; j < i; j++) {
		cout << a[j].amount << "\t\t" << a[j].name << endl;
	}
	cout << a[i].amount * vmax / a[i].weight << "\t\t" << a[i].name << endl;
	cout << "最大化价值:" << maxprice << endl;
}
void main() {
	int n, maxv;
	cout << "请输入物品种类数量:";
	cin >> n;
	cout << "请输入背包承重:";
	cin >> maxv;
	items* good = new items[n];
	cout << "请依次输入物品数量、价格、重量、名字" << endl;
	for (int i = 0; i < n; i++) {
		cin >> good[i].amount >> good[i].price >> good[i].weight >> good[i].name;
	}
	kp(good, 0, n - 1);
	cout << "物品数量\t物品价格\t物品重量\t物品名字" << endl;
	for (int i = 0; i < n; i++) {
		cout << good[i].amount << "\t\t" << good[i].price << "\t\t" << good[i].weight << "\t\t" << good[i].name << endl;
	}
	cout << endl << endl << "--------------------拿取物品--------------------" << endl;
	Knap(good, maxv, n);
	delete[] good;
}

counting game

topic description

Xiaoming’s teacher recently proposed the following number deletion problem to the whole class for everyone to think about: Any given a natural number n consisting of several numbers, it is required to delete the numbers one by one, and delete k numbers in total , making the number of remaining digits the smallest. After Xiao Ming got home, he wrote some numbers for experimentation, and then he came to you and insisted that you check for him whether the result of deleting the numbers was correct. Can you do him a favor?

enter

The first line of input is a positive integer T, indicating that there are T lines of test data below (0<T<=20). There are T lines next, and there are two positive integers n and k on each line, but the effective digit len ​​of the positive integer n can reach 240 bits, and k<len.

output

For each set of test data n, k, output the smallest number of n after deleting k digits. You must delete the leading redundant 0.

sample input

2

178543 4

18541397 4

sample output

13

1137

#include <iostream>
using namespace std;
static int n[100][240];

int main()
{
    int T;
    cin >> T;
    int* k = new int[T];
    string* temp = new string[T];
    for (int i = 0; i < T; i++) {
        cin >> temp[i] >> k[i];
    }
    for (int i = 0; i < T; i++) {
        int length = temp[i].length();
        for (int j = 0; j < length; j++) {
            n[i][j] = temp[i][j] - '0';
        }
        for (int j = 0; j < k[i]; ++j) {
            for (int m = 0; m < length; m++) {
                if (n[i][m] > n[i][m + 1]) {
                    for (int s = m; s < length; s++) {
                        n[i][s] = n[i][s + 1];
                    }
                    length--;
                    break;
                }
            }
        }
        int j = 0, k = 0;
        while (n[i][j] == 0 && k < length - 1) {
            j++;
            k++;
        }
        for (int j = k; j < length; j++) {
            cout << n[i][j];
        }
        cout << endl;
    }
    delete[] k, temp;
    return 0;
}

order of service

topic description

Several customers are waiting for a service at the same time. The service time required by customer i is ti. Your task is to arrange the service sequence of n customers to minimize the total waiting time. The total waiting time refers to the sum of each customer's waiting time for service (you don't have to calculate the service time yourself).

enter

There are several sets of test data, each set of test data has two lines, the first line is an integer n (0<=n<=4000), indicating the number of customers in this test, and the second line is the n customers The required service time is ti, and there is a space between the t of the two customers before and after. There are no extra spaces at the beginning and end of each line, and the customers given in the input are arranged in ascending order.

output

For each set of inputs, output the minimum total wait time for these customers in the test.

sample input

3

4 6 2

5

5 4 3 2 1

sample output

8

20

#include <iostream>
using namespace std;
static int ti[100][200];
static int n[100];

void kp(int a[], int i, int j) {
	if (i > j)
		return;
	int temp = a[i];
	int l = i;
	int r = j;
	while (i != j) {
		while (i < j && a[j] >= temp)
		{
			j--;
		}
		a[i] = a[j];
		while (i < j && a[i] <= temp)
		{
			i++;
		}
		a[j] = a[i];
	}
	a[i] = temp;
	kp(a, l, i - 1);
	kp(a, i + 1, r);
}
void result(int a[],int num) {
	int nownum = num - 1, res = 0;
	for (int i = 0; i < num; i++) {
		res += nownum * a[i];
		nownum--;
	}
	cout << res << endl;
}
int main() {
	int number = 0;
	while (cin >> n[number]) {
		for (int i = 0; i < n[number]; i++)
			cin >> ti[number][i];
		kp(ti[number], 0, n[number]-1);
		number++;
	}
	for (int i = 0; i < number; i++)
		result(ti[i], n[i]);
	return 0;
}

Merge fruit

topic description

In an orchard, Duoduo has knocked down all the fruits and divided them into different piles according to different types of fruits. Duoduo decided to combine all the fruits into one pile. For each merger, Duoduo can merge two piles of fruits together, and the energy consumed is equal to the sum of the weights of the two piles of fruits. It can be seen that after all the fruits have been merged n-1 times, there is only one pile left. The total stamina consumed by Duoduo when merging fruits is equal to the sum of the stamina consumed for each merger.

Because it takes a lot of effort to move these fruits home, Duoduo should save as much energy as possible when merging the fruits. Assuming that the weight of each fruit is 1, and the number of types of fruits and the number of each fruit are known, your task is to design a combined sequence plan that minimizes the energy consumption of Duo Duo, and outputs this minimum energy consumption value.

For example, there are 3 kinds of fruits, the numbers are 1, 2, 9 in turn. You can merge piles 1 and 2 first, the number of new piles is 3, and the energy consumption is 3. Then, merge the new heap with the original third heap to get a new heap, the number is 12, and the energy consumption is 12. So Duoduo consumes a total of physical strength = 3 + 12 = 15. It can be proved that 15 is the minimum physical exertion value.

enter

The input consists of two lines. The first line is an integer n (1 <= n <= 10000), indicating the number of types of fruit. The second line contains n integers, separated by spaces, the i-th integer ai (1 <= ai <= 20000) is the number of the i-th fruit.

output

The output consists of one line, which contains only an integer, which is the minimum physical exertion value. The input data guarantees that this value is less than 2^31.

sample input

3

1 2 9

sample output

15

#include<iostream>
using namespace std;
static long res[1000];
static int num = 0;
void kp(long a[], int i, int j) {
	if (i > j)
		return;
	int temp = a[i];
	int l = i;
	int r = j;
	while (i != j) {
		while (i < j && a[j] >= temp)
		{
			j--;
		}
		a[i] = a[j];
		while (i < j && a[i] <= temp)
		{
			i++;
		}
		a[j] = a[i];
	}
	a[i] = temp;
	kp(a, l, i - 1);
	kp(a, i + 1, r);
}
long hebing(long a[], long n) {
	if (n == 1)
		return 0;
	else if (n == 2)
		return a[0] + a[1];
	long res = a[0] + a[1];
	a[1] = res;
	kp(a, 1, n - 1);
	for (int i = 1; i < n - 1; i++) {
		a[i+1] = a[i] + a[i + 1];
		res = res + a[i+1];
		kp(a, i+1, n - 1);
	}
	return res;
}

int main() {
	long n;
	while (cin >> n) {
		long* a = new long[n];
		long* b = new long[n];
		for (int i = 0; i < n; i++)
			cin >> a[i];
		kp(a, 0, n - 1);
		res[num] = hebing(a, n);
		delete[] a, b;
		num++;
	}
	for (int i = 0; i < num; i++)
		cout << res[i] << endl;
    return 0;
}

budget for village-to-village projects

topic description

A certain city will start the village-to-village project. In the early stage, it was planned to build some rural roads between villages, so that one village can reach another village as long as there is a road. In the later period, roads in adjacent villages will be gradually connected. Of course, wealthy villages will build their own funds. The leaders know the truth of "building roads before getting rich", which is another matter.

The cost of the initial planning is also very considerable, the leaders attach great importance to the budget, and you with excellent programming skills are hired to calculate the minimum cost of village-to-village communication for programming.

enter

There are several sets of test data.

The first line of each set of test data is the number n of villages and the number m of roads that can be built between villages. The next m lines are the description of each road in the budget: there are three integers u, v, and c on each line, which are the numbers of two adjacent villages and the cost of building a direct road, and the number of vertices starts from 1.

output

For each set of test data, output the minimum cost to reach every village.

sample input

3 3

1 2 1

1 3 3

2 3 1

3 2

1 2 1

2 3 3

sample output

2

4

#include<iostream>
using namespace std;
static int res[1000];
static int num = 0;

void kp(int money[], int i, int j, int x[], int y[]) {
	if (i > j)
		return;
	int temp = money[i];
	int temp1 = x[i];
	int temp2 = y[i];
	int l = i;
	int r = j;
	while (i != j) {
		while (i < j && money[j] >= temp)
		{
			j--;
		}
		money[i] = money[j];
		x[i] = x[j];
		y[i] = y[j];
		while (i < j && money[i] <= temp)
		{
			i++;
		}
		money[j] = money[i];
		x[j] = x[i];
		y[j] = y[i];
	}
	money[i] = temp;
	x[i] = temp1;
	y[i] = temp2;
	kp(money, l, i - 1, x, y);
	kp(money, i + 1, r, x, y);
}
bool outside(int a[], int n) {
	for (int i = 0; i < sizeof(a); i++) {
		if (a[i] == n)
			return false;
	}
	return true;
}
int money(int x[], int y[], int z[], int s[], int n, int m) {
	int res = 0;
	int t = 1;
	for (int i = 0; i < m; i++) {
		int a, b;
		a = x[i];
		b = y[i];
		while (s[a] != a)
			a = s[a];
		while (s[b] != b)
			b = s[b];
		if(a!=b){
			s[a] = b;
			t++;
			res += z[i];
		}
		if (t == n)
			break;
	}
	return res;
}
int main() {
	int n, m;
	while (cin >> n) {
		cin >> m;
		int* x = new int[m];//村1
		int* y = new int[m];//村2
		int* z = new int[m];//路费
		int* s = new int[n+1];
		for (int i = 0; i <= n; i++)
			s[i] = i;
		for (int i = 0; i < m; i++) {
			cin >> x[i] >> y[i] >> z[i];
		}
		kp(z, 0, m - 1, x, y);
		res[num] = money(x, y, z, s, n, m);
		delete[] x, y, z, s;
		num++;
	}
	for (int i = 0; i < num; i++)
		cout << res[i] << endl;
	return 0;
}

shortest distance

topic description

Given an undirected graph G=(V, E), and a starting point S and an end point T, please calculate the shortest distance from S to T.

enter

Contains multiple sets of data. The first row of each set of data contains two positive integers n and m (0<n<200, 0<m<1000), respectively representing the number of vertices and edges in the graph. The vertices are numbered from 0 to n-1 respectively.

Next is m lines of road information. Each row has three integers A, B, C (0£A, B<N, A¹B, 0<C<10000), indicating that there is an edge of length C between point A and point B.

Then there are two integers S and T (0£S, T<n) in the next line, which represent the starting point and the ending point respectively. 

output

For each set of data, please output the shortest distance from S to T in one line. If there is no route from S to T, output -1.

sample input

3 3

0 1 1

0 2 3

1 2 1

0 2

3 1

0 1 1

1 2

sample output

2

-1

#include<iostream>
using namespace std;
static int res[1000];
static int num = 0;

int main() {
	int n, m, a, b, c, s, t;
	while (cin >> n) {
		cin >> m;
		int** x = new  int* [n];
		for (int i = 0; i < n; i++) {
			x[i] = new int[n];
		}
		for (int i = 0; i < n; i++) {
			for (int j = 0; j < n; j++) {
				if (i == j)
					x[i][j] = 0;
				else
					x[i][j] = 10000;
			}
		}
		for (int i = 0; i < m; i++) {
			cin >> a >> b >> c;
			if (x[a][b] > c)
				x[b][a] = x[a][b] = c;
		}
		cin >> s >> t;
		for (int k = 0; k < n; k++) {
			for (int i = 0; i < n; i++) {
				for (int j = 0; j < n; j++) {
					x[i][j] = min(x[i][j], x[i][k] + x[k][j]);
				}
			}
		}
		if (x[s][t] >= 10000)
			res[num] = -1;
		else
			res[num] = x[s][t];
		for (int i = 0; i < n; i++) {
			delete[] x[i];
			x[i] = NULL;
		}
		delete[] x;
		num++;
	}
	for (int i = 0; i < num; i++)
		cout << res[i] << endl;
	return 0;
}

Activity sequencing problem

#include <iostream>
#include<string.h>
using namespace std;

void kp(int a[], int b[], int i, int j, int num[]) {
	if (i > j)
		return;
	int temp = a[i];
	int temp2 = b[i];
	int temp3 = num[i];
	int l = i;
	int r = j;
	while (i != j) {
		while (i < j && a[j] >= temp)
		{
			j--;
		}
		a[i] = a[j];
		b[i] = b[j];
		num[i] = num[j];
		while (i < j && a[i] <= temp)
		{
			i++;
		}
		a[j] = a[i];
		b[j] = b[i];
		num[j] = num[i];
	}
	a[i] = temp;
	b[j] = temp2;
	num[j] = temp3;
	kp(a, b, l, i - 1, num);
	kp(a, b, i + 1, r, num);
}
int tanxin(int n, int start[], int end[], int ready[], int num[]) {
	ready[num[0]-1] = 1;//将第一个活动先安排
	int j = 1, count = 1; //活动数量
	for (int i = 1; i < n; i++) {
		if (start[i] >= end[j]) {
			ready[num[i]-1] = 1;
			j = i;
			count++;
		}
		else ready[num[i] - 1] = 0;

	}
	return count;
}
void coutarray(int a[], int n) {
	for (int i = 0; i < n; i++) {
		if (i != n - 1)
			cout << a[i] << "\t";
		else
			cout << a[i] << endl;
	}
}
int main()
{
	int n, count;
	cout << "请输入活动数量:";
	cin >> n;
	int* start = new int[n];//开始时间
	int* end = new int[n];//结束时间
	int* num = new int[n];//活动编号
	int* ready = new int[n];//是否安排
	memset(ready, 0, sizeof(ready));//先全否
	cout << "请输入每组活动开始结束时间:";
	for (int i = 0; i < n; i++) {
		cin >> start[i] >> end[i];
		num[i] = i + 1;
	}
	cout << "活动编号:";
	coutarray(num, n);
	cout << "开始时间:";
	coutarray(start, n);
	cout << "结束时间:";
	coutarray(end, n);
	kp(end, start, 0, n - 1, num);
	count=tanxin(n, start, end, ready, num);
	cout << "是否活动:";
	coutarray(ready, n);
	cout << "活动总数【" << count << "】\n\n" << "-----------------活动项目-----------------\n";
	for(int i=0;i<n;i++){
		if (ready[num[i]-1] == 1)
			cout << endl << "活动编号:" << num[i] << "\t开始时间:" << start[i] << "\t结束时间:" << end[i] << endl;
	}
	delete[] start, end, num, ready;
	return 0;
}

Guess you like

Origin blog.csdn.net/zwyxqzxx/article/details/130187641