河北工业大学2016算法分析与设计实验报告

  1. 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
  2. 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
  3. 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。

【问题描述】
设有 n=2k 个选手要进行网球循环赛,要求设计一个满足以下要求的比赛日 程表: (1)每个选手必须与其他 n-1 个选手各赛一次; (2)每个选手一天只能赛一次; (3)循环赛一共进行 n-1 天. 按照分治的策略,可将所有参赛的选手分为两部分,n=2k 个选手的比赛 日程表就可以通过为 n/2=2k-1 个选手设计的比赛日程表来决定。递归地 执行这种分割,直到只剩下 2 个选手时。
//初始化第 0 行 for(j=0; j<=C; j++) V[0][j]=0; //双重 for 循环完成填表过程 for(i=1; i<=n; i++) for(j=1; j<=C ; j++) if(j<w[i]) V[i][j]=V[i-1][j]; else V[i][j]=max(V[i-1][j], V[i-1][j-w[i]]+v[i]); //从右下角开始往回寻找 for(j=C, i=n; i>0; i--) { if(V[i][j]>V[i-1][j]) { x[i]=1; j-=w[i]; } else x[i]=0; } //返回背包最大价值 return V[n][C]; } int main() { //n 是物品个数;C 是背包总容量 int w[100], v[100], n, C; printf("请输入物品种类:"); scanf("%d",&n); printf("请输入背包重量:"); scanf("%d",&C); printf("请输入重量矩阵:"); for(int i=1; i<=n; i++) scanf("%d",&w[i]);//这里注意 i 从 1 开始取值 printf("请输入价值矩阵:"); for(int i=1; i<=n; i++) scanf("%d",&v[i]);//这里注意 i 从 1 开始取值 printf("\n"); printf("背包取得的最大价值为:%d\n",KnapSack(w, v, n, C)); printf("问题的最优解序列为:"); for(int i=1; i<=n; i++) printf("%2d",x[i]); printf("\n\n");
4 学时
【实验目的】
(1)熟练掌握动态规划思想及教材中相关经典算法。 (2)掌握动态规划算法求解问题的一般特征和步骤;使用动态规划法编 程,求解 0/1 背包问题。
【问题描述】
0/1 背包问题是给定 n 个重量为{w1, w2, … ,wn}、价值为{v1, v2, … ,vn} 的物品和一个容量为 C 的背包, 求这些物品中的一个最有价值的子集,并且要能 够装到背包中。 在 0/1 背包问题中, 物品 i 或者被装入背包, 或者不被装入背包, 设 xi 表示物品 i 装入背包的情况,则当 xi=0 时,表示物品 i 没有被装入背包, xi=1 时,表示物品 i 被装入背包。0/1 背包问题可以看作是决策一个序列(x1, x2, …, xn),对任一变量 xi 的决策是决定 xi=1 还是 xi=0。在对 xi-1 决策后, 已确定了(x1, …, xi-1),在决策 xi 时,问题处于下列两种状态之一: (1)背 包容量不足以装入物品 i,则 xi=0,背包不增加价值; (2)背包容量可以装入物 品 i,则 xi=1,背包的价值增加了 vi。 这两种情况下背包价值的最大者应该是 对 xi 决策后的背包价值。
{ v=j; min=arc[u][j]; } } TSPLength+=arc[u][v]; flag[v]=1;edgeCount++; printf("%d-->", u); u=v; } printf("%d-->%d\n", v, w); return (TSPLength+arc[u][w]); } int main() { #ifdef LOCAL freopen("data.in", "r", stdin); freopen("data.out", "w", stdout); #endif // LOCAL
实验三
【实验学时】
6 学时
【实验目的】
掌握贪心算法求解问题的一般特征和步骤;通过使用贪心算法求解 0/1 背包 和 TSP 问题,进一步加深对贪心算法的理解和运用。
【问题描述】
0/1 背包问题是给定 n 个重量为{w1, w2, … ,wn}、价值为{v1, v2, … ,vn} 的物品和一个容量为 C 的背包, 求这些物品中的一个最有价值的子集,并且要能 够装到背包中每次从物品集合中选择单位重量价值最大的物品, 如果其重量小于 背包容量,就可以把它装入,并将背包容量减去该物品的重量。因此背包问题具 有最优子结构性质。 TSP 问题是指旅行家要旅行 n 个城市然后回到出发城市,要求各个城市经历 且仅经历一次,并要求所走的路程最短。1)最近邻点策略:从任意城市出发, 每次在没有到过的城市中选择最近的一个,直到经过了所有的城市,最后回到出 发城市。2)最短链接策略:每次在整个图的范围内选择最短边加入到解集合中, 但是,要保证加入解集合中的边最终形成一个哈密顿回路。
{ return a.v/a.w > b.v/b.w; } bool cmp2(G a, G b)//按照序号升序排序 { return a.flag < b.flag; } int main() { int i, n, C; double maxValue=0; printf("请输入物品种类:"); scanf("%d",&n); printf("请输入背包重量:"); scanf("%d",&C); printf("请输入重量矩阵:"); for(int i=0; i<n; i++) { scanf("%lf",&good[i].w); good[i].flag=i; } printf("请输入价值矩阵:"); for(int i=0; i<n; i++) scanf("%lf",&good[i].v); sort(good, good+n, cmp1); for(i=0; good[i].w<=C; i++) { good[i].x=1; maxValue+=good[i].v; C-=good[i].w; } good[i].x=(double)C/good[i].w; maxValue+=good[i].x*good[i].v; printf("背包的最大价值为:%.2f\n",maxValue); sort(good, good+n, cmp2);
printf("请输入城市个数:"); scanf("%d",&n); printf("请输入代价矩阵:\n"); for(int i=1; i<=n; i++) for(int j=1; j<=n; j++) { scanf("%d",&arc[i][j]); } printf("请输入起点城市:"); scanf("%d",&w); printf("最短路径为:"); printf("最小代价为:%d", TSP(n, w)); return 0; }
【运行结果】
【分析总结】
本次实验思路简单,并且编程实现也不复杂。通过这次试验,我对于分治法的设 计思想理解地更加深入。 其主要思想就是将一个大问题, 分解为一个个的小问题, 知道每个小问题很容易求出解为止。 最后再将子问题的解合并为一个更大规模的 问题的解,自底向上逐步求出元问题的解。
实验二
【实验学时】
a[i][j]=a[i-temp][j]+temp; for(i=1; i<=temp; i++) for(j=temp+1; j<=n; j++) a[i][j]=a[i+temp][j-temp]; for(i=temp+1;i<=n; i++) for(j=temp+1; j<=n; j++) a[i][j]=a[i-temp][j-temp]; } } int main() { int i,j,k; int a[80][80]; printf("请输入 k 的数值 k="); scanf("%d",&k); GameTable(k,a); for(i=1; i<=pow(2,k); i++) { for(j=1; j<=pow(2,k); j++) printf("%5d",a[i][j]); printf("\n"); } return 0; }
ቤተ መጻሕፍቲ ባይዱ
printf("问题的最优解向量为:"); for(int i=0; i<n; i++) { printf("%.1f ",good[i].x); } printf("\n"); return 0; }
【运行结果】
【TSP 源程序】
#include <stdio.h> //#define LOCAL int arc[10][10]; int n;//城市个数 int w;//起点城市 int TSP(int n, int w) { int edgeCount = 0, TSPLength = 0; int min = 100, u, v; int flag[10]={0};//可以对于 flag 数组中所有元素清零; u=w; flag[w]=1; while(edgeCount < n-1) { min = 100; for(int j=1; j<=n; j++) { if(flag[j]==0 && arc[u][j]<min)
【源程序】
#include<stdio.h> #include<math.h> void GameTable(int k, int a[80][80]) { int n=2; int i, j, t, temp; a[1][1]=1; a[1][2]=2; a[2][1]=2; a[2][2]=1; for (t=1; t<k; t++) { temp=n; n=n*2; for(i=temp+1; i<=n; i++) for(j=1; j<=temp; j++)
【0/1 背包源程序】
//本程序的测试用例来源于课本例题 #include<stdio.h> #include<algorithm> using namespace std; struct G { double v; double w; double x=0; int flag=0; }good[100]; bool cmp1(G a, G b)//按照性价比降序排序
河北工业大学 算法分析与设计 2016 实验报告
学院: 班级: 姓名: 学号:
计算机科学与软件学院
实验一
【实验学时】
4 学时
【实验目的】
1.深刻理解并掌握“分治算法”的设计思想; 2.提高应用“分治算法”设计技能; 3.理解这样一个观点:用递归方法编写的问题解决程序具有结构清晰,可 读性强等优点,且递归算法的设计比非递归算法的设计往往要容易一些,所 以当问题本身是递归定义的,或者问题所涉及到的数据结构是递归定义的, 或者是问题的解决方法是递归形式的时候,往往采用递归算法来解决。
【源程序】
//本程序的测试用例是课本上的例题 #include <stdio.h> int x[100], V[100][100]; int max(int a, int b) { return (a>b ? a : b); } int KnapSack(int w[], int v[], int n, int C) { int i,j; //初始化第 0 列 for(i=0; i<=n; i++) V[i][0]=0;
printf("二维矩阵 V 为:\n"); for(int i=0; i<=n; i++) { for(int j=0; j<=C; j++) printf("%3d",V[i][j]); printf("\n"); } return 0; }
【运行结果】
【分析总结】
通过这次试验, 我体会到了动态规划法设计思想的巧妙之处。动态规划算法通常 用于求解具有某种最优性质的问题。在这类问题中,可能会有许多可行解。每一 个解都对应于一个值, 都希望找到具有最优值的解。 动态规划算法与分治法类似, 其基本思想也是将待求解问题分解成若干个子问题,先求解子问题,然后从这些 子问题的解得到原问题的解。 与分治法不同的是, 适合于用动态规划求解的问题, 经分解得到子问题往往不是互相独立的。
相关文档
最新文档