C++作业: 贪心法求解问题

/*

1. 删数问题:  输入一个数A(例如2838594) 然后输入要删去的个数N(例如 3)  
从数A中删除N个位,使得剩下的结果是最小的(如2354)


2. 有一容量为200的背包。有8种物品,每种的体积和价值如下表。设每种物品都可以取任意数量,
求一种方法使得装进背包的物品的价值总和最大。
A	B	C	D	E	F 	G	H
40	55	20	55	30	40	45	55
35	20	20	40	35	15	40	20

*/

#include <stdio.h>
#include <string.h>

// ------------------ 第1题 -----------------

// 从前n个数字字母中拿走最小的数字, 返回那个被移除的最小数字 
// "28318594" -> 取走"1",剩下"8594" 
static char take_minimum(char* buf, int n)
{
	int len = strlen(buf);
	if(n > len) n = len;

	char min = '9' + 1;
	int  pos = -1;

	for(int i=0; i<n; i++)
	{
		char ch = buf[i];
		if(ch < min)
		{
			min = ch;
			pos = i;
		}
	}

	// 删除前面的数字
	memmove(buf, buf + pos + 1, len - pos);
	return min;
}

static int ex_1(int a, int n)
{
	// 把a转成字符串, 得到长度
	char buf[32] = {0};
	sprintf(buf, "%d", a);
	int  size = strlen(buf);

	// 转换问题, 从a中取m个数, m = size - n
	int m = size - n;

	// 从a中删除n个位置,使剩余的结果最小
	while(m > 0)
	{
		// 每次都在前面几个数中取最小的一个,此为完备算法
		// 可能不算是"贪心算法"

		char min = take_minimum(buf, strlen(buf) - (m-1));
		printf("%c", min); // 打印被取走的数字
		m --;
	}

	return 0;
}

// ------------------ 第2题 -----------------
struct Object
{
	char label; // 标签
	int  volumn;   // 体积
	int  value;    // 价值
	float ratio;   // 价值体积比
	int	 count;		// 填入的数量
};

static int ex2()
{
	/*
	A	B	C	D	E	F 	G	H
		40	55	20	55	30	40	45	55
		35	20	20	40	35	15	40	20
	*/
	int MAX_VOLUMN = 200;
	int i;

	// 使用匿名struct,反正是局部用的
	Object objs[8] =
	{
		{ 'A', 40, 35, 0.0f, 0 },
		{ 'B', 55, 20, 0.0f, 0 },
		{ 'C', 20, 20, 0.0f, 0 },
		{ 'D', 55, 40, 0.0f, 0 },
		{ 'E', 30, 35, 0.0f, 0 },
		{ 'F', 40, 15, 0.0f, 0 },
		{ 'G', 45, 40, 0.0f, 0 },
		{ 'H', 55, 20, 0.0f, 0 }
	};

	// 计算性价比
	for(i=0; i<8; i++)
	{
		objs[i].ratio = (float)  objs[i].value / objs[i].volumn;
	}

	// 排序:按性价比,即value/volumn越大越好, 按ratio从高到低排列
	// 选择排序
	for(i=0; i<7; i++)
	{
		int maxobj = i;
		for(int j=i+1; j<8; j++)
		{
			if(objs[j].ratio > objs[maxobj].ratio)
				maxobj = j;
		}

		// 交换
		if(maxobj != i)
		{
			Object temp = objs[maxobj];
			objs[maxobj] = objs[i];
			objs[i] = temp;
		}
	}
	
	// 贪心法,每次都取性价比最高的来填充
	int total_volumn = 0; // 已占的容量
	for(i=0; i<8; i++)
	{
		if(total_volumn >= MAX_VOLUMN) break;

		Object* obj = &objs[i]; // 按性价比顺序取obj
		int volumn = MAX_VOLUMN - total_volumn; // 剩余容量

		int num = volumn / obj->volumn; // 可以放几个?
		obj->count = num; 
		total_volumn += num * obj->volumn;

		printf("放入:%c,数量:%d x %d, 总容量:%d\n"
			,obj->label, num, obj->volumn, total_volumn);
	}


	return 0;
}

int main()
{
// 	char s[] = "28318594";
// 	char ch = take_minimum(s, 5);

	if(0)
	{
		// 第1题测试

		// 输入一个正整数数
		int a = 0;
		printf("a=");
		scanf("%d", &a);

		// 输入要删除的位数
		int n = 0;
		printf("n=");
		scanf("%d", &n);

		ex_1(a, n);
	}

	if(1)
	{
		// 第2题测试
		ex2();
	}	

	return 0;
}


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

阿发你好

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值