(算法设计与分析)实验五 回溯算法

一、实验目的

理解并实践回溯算法。

二、 实验要求

完成教材第5章11个应用范例中的至少4个(任选3个实现即可)。

三、实验步骤与结果

(1)批处理作业调度
代码:

#include<iostream>
using namespace std;

int x[100];
int bestx[100];
int m[100][100];
int f1=0;
int f2=0;
int cf=0;
int bestf=10000;
int n;

void swap(int &a,int &b)
{
    int temp=a;
    a=b;
    b=temp;
}

void Backtrack(int t)
{
    int tempf,j;
    if(t>n)
    {
        if(cf<bestf)
        {
            for(int i=1; i<=n; i++)
                bestx[i]=x[i];
            bestf=cf;
        }
    }
    else
    {
        for(j=t; j<=n; j++)
        {
            f1+=m[x[j]][1];
            tempf=f2;
            f2=(f1>f2?f1:f2)+m[x[j]][2];
            cf+=f2;
            if(cf<bestf)
            {
                swap(x[t],x[j]);
                Backtrack(t+1);
                swap(x[t],x[j]);
            }
            f1-=m[x[j]][1];
            cf-=f2;
            f2=tempf;
        }
    }
}

int main()
{
    int i,j;
    cout<<"请输入作业数:";
    cin>>n;

    cout<<"请输入各机器上的作业时间:"<<endl<<endl;
    cout<<"作业:  1  2  3"<<endl;
    for(i=1; i<=2; i++)
    {
        cout<<"机器"<<i<<":";
        for(j=1; j<=n; j++)
            cin>>m[j][i];
    }
    for(i=1; i<=n; i++)
        x[i]=i;
    Backtrack(1);

    cout<<endl;
    cout<<"最佳调度方案:";
    for(i=1; i<=n; i++)
    {
        if(i==n)
            cout<<bestx[i];
        else
            cout<<bestx[i]<<"-->";
    }
    cout<<endl;
    cout<<"完成时间:";
    cout<<bestf<<endl;
    return 0;
}

结果:
在这里插入图片描述
(2)0-1背包问题
代码:

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

typedef int Typew;
typedef int Typep;

class Object{
	friend class Knap;
public:
	int operator <= (Object a) const{
		return (d >= a.d);
	}
private:
	int ID;
	Typew w;
	Typep p;
	float d;
};

class Knap{
public:
	Knap(Typew *w, Typep *p, Typew c, int n);
    Typep Knapsack();
	void BackTrack(int floor);
	void print();
private:
	Typep Bound(int i);
	Typew c;
	int n;
	Object *Q;
	Typew cw;
	Typep cp;
	int *cbestx;
	int count;
	int *bestx[10];
	Typep bestp;
	Typep oldbestp;
};

Knap::Knap(Typew *w, Typep *p, Typew c, int n)
{
	Typew W = 0;
	Typep P = 0;
	count = 0;
	this->c = c;
	oldbestp = 0;
	this->n = n;
	cw = 0;
	cp = 0;
	Q = new Object[n];
	for(int i =0; i<n; i++)
	{
		Q[i].ID = i+1;
		Q[i].d = 1.0*p[i]/w[i];
 		Q[i].w = w[i];
		Q[i].p = p[i];
		P += p[i];
		W += w[i];
	}
	if (W <= c)
	{
		bestp = P;
		int *newbestx = new int[n];
		for(int i =0; i<n; i++)
		{
			newbestx[i] = 1;
		}
		bestx[count++] = newbestx;

	}
	for(int i = 0; i<n-1; i++)
		for(int j = 0; j<n-i-1; j++)
		{
			if(Q[j].d < Q[j+1].d)
			{
				Object temp = Q[j];
				Q[j] = Q[j+1];
				Q[j+1] = temp;
			}
		}
}

Typep Knap::Knapsack()
{
	if(count > 0)
	{
		print();
		return bestp;
	}
	else
    {
		cbestx = new int[n];
		BackTrack(0);
	}
	return 1;
}

void Knap::BackTrack(int floor)
{
	if(floor > n-1)
	{
		if( cp == oldbestp )
		{
			int *newbe = new int[n];
			for (int i = 0; i < n; i++)
			{
				newbe[i] = cbestx[i];
			}
			bestx[count++] = newbe;
		}
		if( cp > oldbestp)
		{
			count = 0;
			int *newbe = new int[n];
			for (int i = 0; i < n; i++)
			{
				newbe[i] = cbestx[i];
			}
			bestx[count++] = newbe;
			oldbestp = cp;
		}
	}
	else
	{
		if (c >= cw + Q[floor].w)
		{
			cw += Q[floor].w;
			cp += Q[floor].p;
			if(cp >= bestp)
				bestp = cp;
			cbestx[floor] = 1;
			BackTrack(floor + 1);
			cw -= Q[floor].w;
			cp -= Q[floor].p;
		}
		if(cp + Bound(floor + 1) >= bestp)
		{
			cbestx[floor] = 0;
			BackTrack(floor + 1);
		}

	}
}

void Knap::print()
{
	Typep *original = new int[n+1];
	cout<<"最优方案:"<<endl;
	for (int i = count-1; i >= 0; i--)
	{
		for (int j = 0; j < n; j++)
		{
			original[Q[j].ID] = bestx[i][j];
		}
		for (int k = 1; k <= n; k++)
		{
			cout<< original[k] <<" ";
		}
		cout<<endl;
	}
	cout<<endl;
	cout<<"方案个数:"<<count<<endl<<endl;
	cout<<"背包最大价值:"<<bestp<<endl;
}

Typep Knap::Bound(int i)
{
	Typew cleft = c - cw;
	Typep b = cp;
	while (i < n && Q[i].w <= cleft)
	{
		cleft -= Q[i].w;
		b += Q[i].p;
		i++;
	}
	if(i < n) b += Q[i].p/Q[i].w * cleft;
	return b;
}

int _tmain(int argc, _TCHAR* argv[])
{
	const int N=4;
	Typew c;
	Typew w[N] = {2,2,2,2};
	Typep p[N] = {6,4,8,6};

	cout<<"物品总数:"<<N<<endl;
	cout<<"物品重量:";
	for (int i = 0; i < N; i++)
	{
		cout<<w[i]<<" ";
	}
	cout<<endl;
	cout<<"物品价值:";
	for (int i = 0; i < N; i++)
	{
		cout<<p[i]<<" ";
	}
    cout<<endl<<endl;
    cout<<"请输入背包承重:";
	cin>>c;
	cout<<endl;
	Knap K(w, p, c, N);
	K.Knapsack();
	K.print();
	return 0;
}

结果:
在这里插入图片描述
(3)图的m着色问题
代码:

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

ifstream fin("test.txt");
class Color
{
	friend int mColoring(int, int, int **);
	private:
		bool Ok(int k);
		void Backtrack(int t);
		int n,
			m,
			**a,
			*x;
		long sum;
};

bool Color::Ok(int k)
{
	for (int j=1;j<=n;j++)
	{
		if ((a[k][j]==1)&&(x[j]==x[k]))
		{
			return false;
		}
	}
	return true;
}

void Color::Backtrack(int t)
{
	if (t>n)
	{
		sum++;
		for (int i=1; i<=n; i++)
            cout << x[i] << " ";
		cout << endl;
	}
    else
	{
		for (int i=1;i<=m;i++) {
			x[t]=i;
			if (Ok(t))
                Backtrack(t+1);
            x[t]=0;
		}
	}
}

int mColoring(int n,int m,int **a)
{
	Color X;
	X.n = n;
	X.m = m;
	X.a = a;
	X.sum = 0;
	int *p = new int[n+1];
	for(int i=0; i<=n; i++)
	{
		p[i] = 0;
	}
	X.x = p;
	cout<<"图G的着色方案如下:"<<endl;
	X.Backtrack(1);
	delete []p;
	cout<<endl;
	cout<<"共有方案:";
	return X.sum;
}

int main()
{
    int N = 5;
    int M ;
	int **a = new int *[N+1];
    for(int i=1;i<=N;i++)
    {
        a[i] = new int[N+1];
    }

	cout<<"图G的邻接矩阵为:"<<endl;
	for(int i=1; i<=N; i++)
    {
        for(int j=1; j<=N; j++)
        {
            fin>>a[i][j];
            cout<<a[i][j]<<" ";
        }
        cout<<endl;
    }
    cout<<endl;

    cout<<"请输入颜色数:";
    cin>>M;
	cout<<mColoring(N,M,a)<<endl;
	for(int i=1;i<=N;i++)
    {
        delete[] a[i];
    }
	delete []a;
}

结果:
在这里插入图片描述
(4)旅行销售员问题
代码:

#include <bits/stdc++.h>
#include <iostream>
using namespace std;

const int max_ = 0x3f3f3f;
const int NoEdge = -1;
int citynum;
int edgenum;
int currentcost;
int bestcost;
int Graph[100][100];
int x[100];
int bestx[100];

void InPut()//>>>>
{
    int pos1, pos2, len;
    cout<<"请输入城市数量:";
    cin>>citynum;
    cout<<"请输入路线数:";
    cin>>edgenum;
    memset(Graph, NoEdge, sizeof(Graph));
    cout<<endl;
    cout<<"\t城市  "<<"城市  "<<"距离  "<<endl;
    for(int i = 1; i <= edgenum; ++i)
    {
        cout<<"路线"<<i<<":";
        cin>>pos1>>pos2>>len;
        Graph[pos1][pos2] = Graph[pos2][pos1] = len;
    }
}
void Initilize()
{
    currentcost = 0;
    bestcost = max_;
    for(int i = 1; i <= citynum; ++i)
    {
        x[i] = i;
    }
}
void Swap(int &a, int &b)
{
    int temp;
    temp = a;
    a = b;
    b = temp;
}
void BackTrack(int i) //这里的i代表第i步去的城市而不是代号为i的城市
{
    if(i == citynum)
    {
        if(Graph[x[i - 1]][x[i]] != NoEdge && Graph[x[i]][x[1]] != NoEdge && (currentcost + Graph[x[i - 1]][x[i]] + Graph[x[i]][x[1]] < bestcost || bestcost == max_))
        {
            bestcost = currentcost + Graph[x[i - 1]][x[i]] + Graph[x[i]][x[1]];
            for(int j = 1; j <= citynum; ++j)
                bestx[j] = x[j];
        }
    }
    else
    {
        for(int j =  i; j <= citynum; ++j)
        {
            if(Graph[x[i - 1]][x[j]] != NoEdge && (currentcost + Graph[x[i - 1]][x[j]] < bestcost || bestcost == max_))
            {
                Swap(x[i], x[j]);  //这里i 和 j的位置交换了, 所以下面的是currentcost += Graph[x[i - 1]][x[i]];
                currentcost += Graph[x[i - 1]][x[i]];
                BackTrack(i + 1);
                currentcost -= Graph[x[i - 1]][x[i]];
                Swap(x[i], x[j]);
            }
        }
    }
}
void OutPut()
{
    cout<<endl;
    cout << "最短路线:" <<endl;
    for(int i = 1; i <= citynum; ++i)
    {
        if(i==citynum)
            cout <<"城市"<< bestx[i];
        else
            cout <<"城市"<< bestx[i] << "-->";
    }

    cout << "-->城市1" << endl;
}

int main()
{
    InPut();
    Initilize();
    BackTrack(2);
    OutPut();
}


结果:
在这里插入图片描述

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值