【数据结构】数据结构与算法综合实验

  • 实验目的与要求

熟悉C/C++语言的集成开发环境;

通过本实验加深对分治法、贪心算法的理解。

  • 实验内容:

掌握分治法、贪心算法的概念和基本思想,并结合具体的问题学习如何用相应策略进行求解的方法。

  • 实验题

1. 【伪造硬币问题】给你一个装有n个硬币的袋子。n个硬币中有一个是伪造的。你的任务是找出这个伪造的硬币。为了帮助你完成这一任务,将提供一台可用来比较两组硬币重量的仪器,利用这台仪器,可以知道两组硬币的重量是否相同。试用分治法的思想写出解决问题的算法,并计算其时间复杂度。

#include<iostream>
using namespace std;

int find_fake(int a[],int low,int high)
{
	int sum1, sum2, sum3;
	sum1 = sum2 = sum3 = 0;
	int fake=0;
	if (low + 1 == high)
	{
		if (a[low] < a[high])
		{
			fake = low;
			return fake;
		}
		else
		{
			fake = high;
			return fake;
		}
	}

	if ((high - low + 1) % 2 == 0)//偶数个
	{
		int mid = low + (high - low + 1) / 2 - 1;
		for (int i = low;i <= mid;i++)
		{
			sum1 += a[i];
		}
		for (int i = mid+1 ;i <= high;i++)
		{
			sum2 += a[i];
		}
		if (sum1 < sum2)
		{
			fake = find_fake(a, low, mid);
			return fake;
		}
		if (sum1 > sum2)
		{
			fake = find_fake(a, mid+1, high);
			return fake;
		}
	}
	else						//当长度为奇数的时候 
	{
		int mid = low + (high - low) / 2 ;
		for (int i = low;i <=mid-1;i++)	//对前半段求和
		{
			sum1 += a[i];
		}
		for (int i = mid+1;i <= high;i++)//对后半段求和
		{
			sum2 += a[i];
		}
		sum3 = a[low + (high - low) / 2];			//sum3用于存放中间数据 
		if (sum1 < sum2)					//假币在前半段 
		{
			fake = find_fake(a, low, mid-1);
			return fake;
		}
		else if (sum1 > sum2)
		{
			fake = find_fake(a, mid, high);
			return fake;
		}
		else if (sum1 + sum3 == sum2 + sum3)	//中间的那个就是假币
		{
			fake = (high - low) / 2 + 1;
			return fake;
		}
	}
}

int main()
{
	int n=0;
	int fake = 0;
	cout << "请输入硬币总数n:";
	cin >> n;
	int* a = new int[n+1];
	cout << "请依次输入硬币的重量:";
	for (int i = 1;i <= n;i++)
	{
		cin >> a[i];
	}
	fake=find_fake(a, 1, n);
	cout << "第" << fake << "枚硬币是假的。" << endl;
}

2.【找零钱问题】一个小孩买了价值为33美分的糖,并将1美元的钱交给售货员。售货员希望用数目最少的硬币找给小孩。假设提供了数目有限的面值为25美分、10美分、5美分、及1美分的硬币。给出一种找零钱的贪心算法。

#include<iostream>
using namespace std;

void getmax(int& x)
{
	int m=0;
	int record[4] = { 0 };
	while (x >= 25)
	{
		record[3]++;
		x -= 25;
	}
	while (x >= 10)
	{
		record[2]++;
		x -= 10;
	}
	while (x >= 5)
	{
		record[1]++;
		x -= 5;
	}
	while (x >= 1)
	{
		record[0]++;
		x -= 1;
	}
	cout << "需要找回" << record[3] << "张25美分," << record[2] << "张10美分," << record[1] << "张5美分," << record[0] << "张1美分。";
}

int main()
{
	int prise = 0;
	int give = 0;
	cout << "请问商品的原价为:";
	cin >> prise;
	cout << endl;
	cout << "请问顾客付款为:";
	cin >> give;
	cout << endl;
	int back = give - prise;
	getmax(back);
}

算法实现二

  • 实验目的与要求

熟悉C/C++语言的集成开发环境;

通过本实验加深对贪心算法、动态规划和回溯算法的理解。

  • 实验内容:

掌握贪心算法、动态规划和回溯算法的概念和基本思想,分析并掌握"0-1"背包问题的三种算法,并分析其优缺点。

  • "0-1"背包问题的贪心算法
  • #include<iostream>
    using namespace std;
    
    struct things
    {
    	int value;
    	int weight;
    };
    
    int main()
    {
    	int n = 0;//物品总数
    	int c = 0;//背包容量
    	cout << "请输入物品总数n:";
    	cin >> n;
    	cout << "请输入背包容量:";
    	cin >> c;
    	things* t = new things[n];
    	for (int i = 0;i < n;i++)
    	{
    		cout << "请依次输入第" << i + 1 << "件物品的价值、重量:";
    		cin >> t[i].value >> t[i].weight;
    	}
    	for (int i = 0;i < n;i++)
    	{
    		for (int j = 0;j < n - 1;j++)
    		{
    			if ((t[i].value / t[i].weight) < (t[i + 1].value / t[i + 1].weight))
    			{
    				things temp = t[i];
    				t[i] = t[i + 1];
    				t[i + 1] = temp;
    			}
    		}
    	}
    	//贪心算法
    	int weight_sum = 0;
    	int vaule_sum = 0;
    	int k = 0;
    	while (weight_sum < c && k < n)
    	{
    		if (weight_sum + t[k].weight <= c)
    		{
    			weight_sum += t[k].weight;
    			vaule_sum += t[k].value;
    		}
    		k++;
    
    	}
    	cout << "一共装入了价值为" << vaule_sum << "的物品。" << endl;
    }

  • "0-1"背包问题的动态规划算法
  • #include<iostream>
    #include<iomanip>
    using namespace std;
    
    int main()
    {
    	int n = 0;//物品总数
    	int c = 0;//背包容量
    	cout << "请输入物品总数n:";
    	cin >> n;
    	cout << "请输入背包容量:";
    	cin >> c;
    	int* value = new int[n];
    	int* weight = new int[n];
    	for (int i = 0;i < n;i++)
    	{
    		cout << "请依次输入第" << i + 1 << "件物品的价值、重量:";
    		cin >> value[i] >> weight[i];
    	}
    
    	int** maxValue = new int*[n];
    	for (int i = 0;i < n;i++)
    	{
    		maxValue[i] = new int[c];
    	}
    	for (int i = 0;i < n;i++)
    	{
    		for (int j = 0;j < c;j++)
    		{
    			maxValue[i][j] = 0;
    		}
    	}
    
    	//填充表格
    	for (int i = 0;i < n;i++)
    	{
    		for (int j = 1;j <= c;j++)
    		{
    			if (i == 0)
    			{
    				maxValue[i][j - 1] = (weight[i] <= j ? value[i] : 0);
    			}
    			else
    			{
    				int topValue = maxValue[i - 1][j - 1];//上一个值
    				int nowValue = (weight[i] <= j ?
    					(j - weight[i] > 0 ? value[i] + maxValue[i - 1][j - weight[i]-1] : value[i]) 
    					: topValue);//比较重量
    				maxValue[i][j - 1] = (topValue > nowValue ? topValue : nowValue);
    			}
    		}
    	}
    
    	for (int i = 0;i < n;i++)
    	{
    		for (int j = 0;j < c;j++)
    		{
    			cout << setw(7) << maxValue[i][j] ;
    		}
    		cout << endl;
    	}
    	cout << "背包能装入的最大价值为:" << maxValue[n-1][c-1];
    }
    
    

  • "0-1"背包问题的回溯算法
#include<iostream>
#include<cmath>
using namespace std;

struct things
{
	int judge;
	int value;
	int weight;
};
int maxv = 0;
void backtrace(things t[],int c,int now,int &max,int n)
{
	static int w = 0;
	static int v = 0;
	if (now+1 == n)
	{
		if (v > max && w <= c)
		{
			max = v;
			maxv = max;
		}
		return;
	}
	//没有背该物品
	backtrace(t, c, now + 1, max, n);
	//背了
	w += t[now].weight;
	v += t[now].value;
	backtrace(t, c, now + 1, max, n);
	w -= t[now].weight;
	v -= t[now].value;
}

int main()
{
	int n = 0;//物品总数
	int c = 0;//背包容量
	cout << "请输入物品总数n:";
	cin >> n;
	cout << "请输入背包容量:";
	cin >> c;
	int max = 0;
	things* t = new things[n];
	for (int i = 0;i < n;i++)
	{
		cout << "请依次输入第" << i + 1 << "件物品的价值、重量:";
		cin >> t[i].value>>t[i].weight;
	}
	for (int i = 0;i < n;i++)     //排序
	{
		for (int j = 0;j < n - 1;j++)
		{
			if ((t[i].value / t[i].weight) < (t[i + 1].value / t[i + 1].weight))
			{
				things temp = t[i];
				t[i] = t[i + 1];
				t[i + 1] = temp;
			}
		}
	}
    backtrace(t, c, 0 ,max, n);
	cout << "一共背入价值为" << maxv << "的物品";
}

  • 0
    点赞
  • 7
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值