【算法设计与分析】第七至十一讲实验

 7:

1. 实验题目

给定一个非负整数的数组,每个数字表示在当前位置的基础上最多可以走的步数。求能够到达数组最后一个位置所需的最少移动次数。如果不能到达,则输出-1。

例如:

       输入数组 [2,3,1,1,4],输出2——第一步从下标0移动1步到下标1,再移动3步到最后一个位置。

       输入数组 [3,2,1,0,4],不能到达,输出-1——无论怎么移动都只能到下标为3的位置,在此位置最多只能移动0步,故永远无法到达最后位置。

2. 实验目的

    掌握贪心法的设计思想并能熟练运用。

3. 实验要求

    设计贪心算法求解。输出最小移动次数,如果不能到达,则输出-1。

#include <iostream>
using namespace std;

int Greedy(int x[], int length);

int main()
{

    int length;
    int x[1000];
    cin >> length;

    for (int i = 0; i < length; i++)
    {
		cin >> x[i];
    }

    cout << Greedy(x, length) << endl;

    return 0;
}

int max(int a, int b) {
    if (a >= b)
        return a;
    return b;
}

int Greedy(int x[], int length) {
int end=length-1,steps=0,k=0,i;
    for(i=0;i<length-1;i++){
        if(i<=k && i+x[i]>k){
            k = i+x[i];
        }
    }
    if(k<length-1){
    	steps=-1;
    	return steps;
	}
    else{
    	while(end>0){
		    for(i=0;i<end;i++){
			    if(i+x[i]>=end){
				    end=i;
				    steps++;
				    break;
			    }
		    }
	    }
	    return steps;
	}
}

8: 

1. 实验题目

给定n种物品和一个容量为C的背包,物品i的重量是wi,其价值为vi,0/1背包问题是如何选择装入背包的物品(物品不可分割),使得装入背包中物品的总价值最大?

2. 实验目的

(1)掌握回溯法的设计思想;

(2)掌握解空间树的构造方法,以及在求解过程中如何存储求解路径;

(3)考察回溯法求解问题的有效程度。

3. 实验要求

(1)对于输入的重量和价值数组,及背包容量,输出可装入的最大价值;

(2)思考可能解的表示方式及解空间树的构造;

(3)使用回溯算法完成问题求解。

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

int maxValue(int w[], int v[], int length, int capacity);

int main()
{
	int length;
	int knapsack_capacity;	

	int w[1000];
	int v[1000];

	cin >> length;

	for (int i = 0; i < length; i++)
	{
		cin >> w[i];
	}
	for (int i = 0; i < length; i++)
	{
		cin >> v[i];
	}

	cin >> knapsack_capacity;

	cout << maxValue(w, v, length, knapsack_capacity);
}

int Max(int a,int b)
{
	if(a>b)
	{
		return a;
	}
	else
	{
		return b;
	}
}

int maxValue(int w[],int v[],int length,int capacity)
{
    int dp[capacity+1],i,j,k,max=0;
    for(j=0;j<=capacity;j++)
	{
        dp[j] = 0;
    }
    for(i=0;i<length;i++)  //鍙嶅悜鏋氫妇 
	{
        for(k=capacity;k>=w[i];k--)
		{
            dp[k] = Max(dp[k],dp[k-w[i]]+v[i]);
        }
    }
    for(i=0;i<=capacity;i++)
	{
        max= Max(max,dp[i]);
    }
    return max;
} 

9: 

1. 实验题目

印刷电路板将布线区域划分成n×n个方格。精确的电路布线问题要求确定连接方格a到方格b的最短布线方案。在布线时,电路只能沿着直线或直角布线,也就是不允许线路交叉。

2. 实验目的

进一步掌握分支限界法的设计思想,掌握限界函数的设计技巧。

3. 实验要求

对问题建立合理的模型,采用分支限界法求解。

4. 实现提示

(1)下图所示是一块准备布线的电路板。在布线时, 电路只能沿直线或直角布线。为了避免线路相交, 已布线的方格做了封锁标记(图中用阴影表示) , 其他线路不允许穿过被封锁的方格。

(2)电路板子用一个二维数组C[n][n]表示,其中C[i][j] = 1表示被封锁(阴影),C[i][j] = 0表示未封锁;输入起点a的行列号[r0, c0]和终点b的行列号[r1, c1],要求输出从a到b的路径,用行列坐标表示,从0开始计数。

(3)用分支限界法求解电路布线问题, 从起始方格a开始作为根结点, 与起始位置a相邻且可达的方格成为可行结点, 连同从起始方格到这个方格的距离1 加入待处理结点表PT中(可用队列存储表PT)。然后, 从表PT中取出队首结点成为下一个扩展结点, 将与当前扩展结点相邻且可达的方格连同从起始方格到这个方格的距离2加入表PT中。重复上述过程, 直到达到目标方格b或表PT为空。

#include <iostream>
using namespace std;

int distance(int** c, int n, int a_row, int a_col, int b_row, int b_col);

int main()
{
	int n, a_row, a_col, b_row, b_col;
	cin >> n >> a_row >> a_col >> b_row >> b_col;

	int** c = new int*[n];
	for (int i = 0; i < n; i++)
	{
		c[i] = new int[n];
		for (int j = 0; j < n; j++)
		{
			cin>>c[i][j];
		}
	}

	cout << distance(c, n, a_row, a_col, b_row, b_col);
}
#include <climits>
using namespace std;

int** t; 
int direction[4][2]={{0,1},{0,-1},{1,0},{-1,0}};  //鍥涗釜鏂瑰悜鍋忕Щ锛寈鍜?y鐨勫潗鏍囧€煎垎鍒姞鍑?1 

int min(int& a,int& b)  //姹備簩鑰呰緝灏忓€?
{
	return a<=b ? a:b;
}

int DFS_Search(int** c,int n,int a_row,int a_col,int b_row,int b_col)  //娣卞害浼樺厛鎼滅储 
{
	if(t[a_row][a_col]>=0)
	{
	    return t[a_row][a_col];
	}
	c[a_row][a_col]=1;
	int max=INT_MAX;
	for(int i=0;i<4;i++)
	{
		int ax=a_row+direction[i][0];
		int ay=a_col+direction[i][1];
		if(ax>=0 && ax<n && ay>=0 && ay<n && c[ax][ay]==0)
		{
			if(DFS_Search(c,n,ax,ay,b_row,b_col)<INT_MAX)
			{
			    max=min(max,t[ax][ay]+1);
			} 
		}
	}
	t[a_row][a_col]=max;
	c[a_row][a_col]=0;
	return t[a_row][a_col];
}

int distance(int** c,int n,int a_row,int a_col,int b_row,int b_col)  //姹傛渶鐭窛绂?
{
	int i,j;
	if(a_row==b_row && a_col==b_col)  //鍘熷湴涓嶅姩 
	{
		return 0;
	} 
	t=new int*[n];
	for(i=0;i<n;i++)
	{
		t[i]=new int[n];
		for(j=0;j<n;j++)
		{
			t[i][j]=-1;
		}
	}
	t[b_row][b_col]=0;
	return DFS_Search(c,n,a_row,a_col,b_row,b_col);
}

10:

1. 实验题目

采用拉斯维加斯型概率算法求解八王后问题。

2. 实验目的

(1)掌握概率算法的求解思路;

(2)通过运用拉斯维加斯型概率算法体会提升算法效率的设计过程。

3. 实验要求

(1)设计求解八王后问题的算法,使用拉斯维加斯型概率算法提升效率;

(2)将求解结果用二维数组表示,并观测求解时间,需尽力使性能达到最优;

(3)阅读已给出的代码,程序以cout输出的结果作为判断,正确输出1,错误输出0,在空白处填入函数Queen()的实现代码。

#include <iostream>
#include<vector>
using namespace std;

bool chess[8][8] = {
	{0,0,0,0,0,0,0,0},		
	{0,0,0,0,0,0,0,0},
	{0,0,0,0,0,0,0,0},
	{0,0,0,0,0,0,0,0},
	{0,0,0,0,0,0,0,0},
	{0,0,0,0,0,0,0,0},
	{0,0,0,0,0,0,0,0},
	{0,0,0,0,0,0,0,0},
};

void Queen();

int main()
{
	Queen();

	vector<int> x;
	vector<int> y;
	for (int m = 0; m < 8; m++)
	{
		for (int n = 0; n < 8; n++)
		{
			if (chess[m][n])
			{
				x.push_back(m);
				y.push_back(n);
			}
		}
	}

	if (x.size() != 8 || y.size() != 8)
	{
		cout << false;
		return 0;
	}

	for (int i = 0; i < 7; i++)
	{
		for (int j = i+1; j < 8; j++)
		{
			if (x[i] == x[j] || y[i] == y[j] || x[i] - x[j] == y[i] - y[j] || x[i] - x[j] == y[j] - y[i])
			{
				cout << false;
				return 0;
			}
		}
	}

	cout << true;
	return 0;
}

int x[8]={0};

bool position(int i,int x[])  //鍒ゆ柇鏄惁鍙斁缃?
{
    int j,k;
    for(j=0;j<i;j++)
	{
        if(x[i]==x[j]||abs(x[i]-x[j])==abs(i-j))  //绾︽潫鏉′欢鍒ゆ柇 
		{
			return false;
		}
    }
     return true;
}

void Queen() 
{
    int i,j,flag=1;
    while(flag)
	{
        for(i=0;i<8;i++)
	    {
            x[i]=rand()%8;  //鐢熸垚0~7闅忔満鏁?
            if(position(i,x))  //鏀剧疆鎴愬姛锛岃烦杞嚦涓嬩竴涓殗鍚庢斁缃?
            {
			    continue;  //缁х画鎵ц寰幆 
			}
            else  //鎵ц澶辫触 
		    {
               break;
            }
        }
        if(i==8)
        {
		    flag=0;
		}
    }
    for(j=0;j<8;j++)
	{
        chess[j][x[j]]=1;
    }
}

11:

1. 实验题目

设计求解TSP问题的近似算法。

2. 实验目的

掌握近似算法的设计。

3. 实验要求

(1) 输入一系列平面上的点,将任意两点之间以直线相连,构成一个无向连接图。

 (2) 设计近似算法求解满足三角不等式的TSP问题,要求近似比不超过2。

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

int* tsp(double* px, double* py, int length);

int main()
{
	int length;
	double optimal;

	cin >> length;
	cin >> optimal;

	double x[1000];
	double y[1000];

	for (int i = 0; i < length; i++)
	{
		cin>>x[i];
	}
	for (int i = 0; i < length; i++)
	{
		cin>>y[i];
	}

	int* path = tsp(x, y, length);
	double cost = 0;
	for (int k = 0; k < length; k++)
	{
		int a = path[k];
		int b = path[(k + 1) % length];

		double d = (x[a] - x[b])* (x[a] - x[b]) + (y[a] - y[b])*(y[a] - y[b]);
		if (d == 0)
		{
			cout << 0 << endl;
			return 0;
		}
		cost += sqrt(d);
	}
	
	if (cost > 2 * optimal)
	{
		cout << 0 << endl;
		return 0;
	}
	cout << 1 << endl;
}
int* tsp(double* px, double* py, int length){
    int* path = new int[length];     //鍒涘缓涓€涓暟缁勬潵瀛樺偍璺緞
    bool* visited = new bool[length];   //鍒涘缓涓€涓暟缁勬潵鏍囪鏄惁琚闂繃

    for (int i = 0; i < length; i++){
        visited[i] = false;      //鍒濆鍖栨墍鏈夌偣鐨勮闂姸鎬佷负鏈闂?
    }

    path[0] = 0;         //闅忔満閫夋嫨涓€涓捣鐐癸紝骞跺皢鍏舵爣璁颁负宸茬粡璁块棶
    visited[0] = true;

    for (int i = 1; i < length; i++){
        int last = path[i - 1];   //涓婁竴涓偣
        int next = -1;       //涓嬩竴涓璁块棶鐨勭偣
        double minDist = -1;      //鍒颁笅涓€涓偣鐨勬渶鐭窛绂?

        for (int j = 0; j < length; j++){
            if (!visited[j]){
                double dist = sqrt((px[last] - px[j]) * (px[last] - px[j]) + (py[last] - py[j]) * (py[last] - py[j]));
                if (minDist < 0 || dist < minDist){
                	//鎵惧埌璺濈鏈€灏忕殑鐐?
                    minDist = dist;
                    next = j;
                }
            }
        }
        path[i] = next;         //灏嗕笅涓€涓偣鍔犲叆璺緞
        visited[next] = true;   //鏍囪涓哄凡璁块棶
    }
    return path;
}

  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

MorleyOlsen

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

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

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

打赏作者

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

抵扣说明:

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

余额充值