알고리즘 및 분석 학습 주제 기록 - Greedy Method

목차

10 배낭 질문

임의의 배낭 문제

카운팅 게임

서비스 순서

과일 병합

마을 간 프로젝트 예산

최단 거리

활동 시퀀싱 문제


10 배낭 질문

#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;
}

임의의 배낭 문제

#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;
}

카운팅 게임

주제 설명

Xiaoming의 선생님은 최근 모든 사람들이 생각해 볼 수 있도록 다음과 같은 숫자 삭제 문제를 전체 학급에 제안했습니다. 여러 숫자로 구성된 자연수 n이 주어지면 숫자를 하나씩 삭제하고 총 k개의 숫자를 삭제해야 합니다. 남은 자릿수가 가장 작은 것. Xiao Ming은 집에 돌아온 후 실험을 위해 몇 가지 숫자를 적고 나서 당신에게 와서 숫자를 삭제한 결과가 올바른지 확인하라고 주장했습니다.

입력하다

입력의 첫 번째 줄은 양의 정수 T이며 아래에 T 줄의 테스트 데이터가 있음을 나타냅니다(0<T<=20). 다음으로 T개의 라인이 있고, 각 라인에는 양의 정수 n과 k가 2개 있는데, 양의 정수 n의 유효숫자 len은 240비트에 이를 수 있고, k<len이다.

산출

테스트 데이터 n, k의 각 집합에 대해 k자리를 삭제한 후 가장 작은 n개를 출력합니다.리딩 중복 0을 삭제해야 합니다.

샘플 입력

2

178543 4

18541397 4

샘플 출력

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;
}

서비스 순서

주제 설명

여러 고객이 동시에 서비스를 기다리고 있습니다. 고객 i가 요구하는 서비스 시간은 ti입니다. 귀하의 임무는 총 대기 시간을 최소화하기 위해 n 고객의 서비스 순서를 조정하는 것입니다. 총 대기시간은 각 고객의 서비스 대기 시간의 합계를 의미합니다(서비스 시간을 직접 계산할 필요는 없습니다).

입력하다

여러 개의 테스트 데이터 세트가 있으며 각 테스트 데이터 세트에는 두 개의 라인이 있습니다. 첫 번째 라인은 이 테스트의 고객 수를 나타내는 정수 n(0<=n<=4000)이고 두 번째 라인은 n입니다. 고객 서비스 소요 시간은 ti이며 전후 두 고객의 t 사이에 공백이 있습니다. 각 줄의 시작과 끝에 여분의 공백이 없으며 입력된 고객이 오름차순으로 정렬됩니다.

산출

각 입력 집합에 대해 테스트에서 이러한 고객에 대한 최소 총 대기 시간을 출력합니다.

샘플 입력

4 6 2

5

5 4 3 2 1

샘플 출력

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;
}

과일 병합

주제 설명

과수원에서 Duoduo는 모든 과일을 쓰러뜨려 과일 종류에 따라 다른 더미로 나누었습니다. Duoduo는 모든 과일을 하나의 더미로 결합하기로 결정했습니다. 병합할 때마다 Duoduo는 두 개의 과일 더미를 병합할 수 있으며 소비되는 에너지는 두 과일 더미의 무게를 합한 것과 같습니다. 모든 과일이 n-1번 병합된 후 단 하나의 더미만 남아 있음을 알 수 있습니다. 듀오 듀오가 과일 합체 시 소모하는 스태미나 총량은 각 합체 시 소모하는 스태미너 합과 동일합니다.

이러한 과일을 집으로 옮기는 데 많은 노력이 필요하기 때문에 Duoduo는 과일을 병합할 때 가능한 한 많은 에너지를 절약해야 합니다. 각 과일의 무게가 1이고, 과일의 종류와 개당 개수를 알고 있다고 가정하면 듀오 듀오의 에너지 소비를 최소화하고 이 최소 에너지 소비를 출력하는 결합 시퀀스 계획을 설계하는 것이 과제입니다. 값.

예를 들어, 3가지 종류의 과일이 있고 숫자는 차례로 1, 2, 9입니다. 파일 1과 2를 먼저 병합할 수 있으며 새 파일의 수는 3개이고 에너지 소비량은 3입니다. 그런 다음 새 힙을 원래의 세 번째 힙과 병합하여 새 힙을 얻습니다. 숫자는 12이고 에너지 소비량은 12입니다. 따라서 Duoduo는 총 체력 = 3 + 12 = 15를 소모합니다. 15가 최소 신체 활동 값임을 증명할 수 있습니다.

입력하다

입력은 두 줄로 이루어지며, 첫 번째 줄은 정수 n(1 <= n <= 10000)으로 과일 종류의 수를 나타냅니다. 두 번째 줄에는 공백으로 구분된 n개의 정수가 포함되며 i번째 정수 ai(1 <= ai <= 20000)는 i번째 과일의 번호입니다.

산출

출력은 최소 물리적 노력 값인 정수만 포함하는 한 줄로 구성됩니다. 입력 데이터는 이 값이 2^31 미만임을 보장합니다.

샘플 입력

1 2 9

샘플 출력

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;
}

마을 간 프로젝트 예산

주제 설명

어떤 도시에서 마을 대 마을 프로젝트를 시작할 것입니다. 초기에는 마을과 마을 사이에 시골길을 만들어 도로만 있으면 한 마을에서 다른 마을로 갈 수 있도록 계획했다. 후기에는 인접한 마을의 도로가 점차 연결될 것입니다.물론 부유한 마을은 자체 자금을 마련할 것입니다.지도자는 "부자가 되기 전에 도로를 건설하는 것"의 진실을 알고 있습니다.

초기 계획 비용도 매우 상당하고, 리더는 예산을 매우 중요하게 생각하며 프로그래밍을 위한 마을 간 통신의 최소 비용을 계산하기 위해 뛰어난 프로그래밍 기술을 가진 당신을 고용합니다.

입력하다

여러 테스트 데이터 세트가 있습니다.

각 테스트 데이터 세트의 첫 번째 줄은 마을의 수 n과 마을 사이에 건설할 수 있는 도로의 수 m입니다. 다음 m 줄은 예산의 각 도로에 대한 설명입니다. 각 줄에는 세 개의 정수 u, v 및 c가 있으며, 이는 인접한 두 마을의 수와 직접 도로 건설 비용 및 꼭지점 수입니다. 1부터 시작합니다.

산출

각 테스트 데이터 세트에 대해 모든 마을에 도달하기 위한 최소 비용을 출력합니다.

샘플 입력

3 3

1 2 1

1 3 3

2 3 1

3 2

1 2 1

2 3 3

샘플 출력

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;
}

최단 거리

주제 설명

무방향 그래프 G=(V, E), 시작점 S와 끝점 T가 주어지면 S에서 T까지의 최단 거리를 계산하십시오.

입력하다

여러 데이터 세트를 포함합니다. 각 데이터 집합의 첫 번째 행에는 두 개의 양의 정수 n과 m(0<n<200, 0<m<1000)이 포함되어 있으며 각각 그래프의 정점과 가장자리 수를 나타냅니다. 정점은 각각 0에서 n-1까지 번호가 지정됩니다.

다음은 m 라인의 도로 정보입니다. 각 행에는 3개의 정수 A, B, C(0£A, B<N, A¹B, 0<C<10000)가 있으며 이는 점 A와 점 B 사이에 길이가 C인 가장자리가 있음을 나타냅니다.

그러면 다음 줄에 각각 시작점과 끝점을 나타내는 두 개의 정수 S와 T(0£S, T<n)가 있습니다. 

산출

각 데이터 세트에 대해 S에서 T까지의 최단 거리를 한 줄에 출력하십시오. S에서 T로 가는 경로가 없으면 -1을 출력합니다.

샘플 입력

3 3

0 1 1

0 2 3

1 2 1

0 2

3 1

0 1 1

1 2

샘플 출력

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;
}

활동 시퀀싱 문제

#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;
}

Supongo que te gusta

Origin blog.csdn.net/zwyxqzxx/article/details/130187641
Recomendado
Clasificación