某农业学校 算法设计与分析-实验6-分支限界法实验

1. 用分治限界法解决0-1背包问题

【问题描述】

给定n个重量为wi,价值为vi的物品(i=1,2,…,n),以及一个重量为W的背包,找出其中最有价值的物品子集,并且能全部放入背包中。

【输入形式】

第一行是背包重量上限,第二、三、四、五行是物品的重量和价值

【输出形式】

能够放入背包的物品最大价值

【样例输入】

10

7 42

3 12

4 40

5 25

【样例输出】

65

#include<bits/stdc++.h>
using namespace std;
/*
10
7 42
3 12
4 40
5 25
*/
int n,w[1010],v[1010],C,maxx;

void bound(int i,int noww,int nowv)
{
	if(i>n)
	{
		if(nowv>maxx)
		{
			maxx=nowv;
		}
		return ;
	}
	for(int j=0;j<=1;j++)
	{
		nowv+=v[i]*j;
		noww+=w[i]*j;
		if(noww<=C && nowv+v[i+1]>maxx)
		{
			bound(i+1,noww,nowv);
		}
	}
	return ;
}
 
int main()
{
	cin>>C;
	n=4;
	for(int i=1;i<=n;i++)
	{
		cin>>w[i]>>v[i];
	}
	for(int i=1;i<n;i++)
	{
		bound(i+1,w[i],v[i]);	
	}
	cout << maxx;
	return 0;
}

2. 单源最短路径

【问题描述】

给定带权有向图G =(V,E),其中每条边的权是非负实数。另外,还给定V中的一个顶点,称为源(默认源点为顶点1)。现在要计算从源到所有其他各顶点的最短路长度。这里路的长度是指路上各边权之和。这个问题通常称为单源最短路径问题。

【输入形式】

第一行是顶点数n和边数m

随后n行是顶点编号

随后m行是所有边的起点 终点和边长

【输出形式】

输出n-1行,分别为源点到其他各点的最短路径

【样例输入】

5 6

1

2

3

4

5

1 2 5

2 5 1

1 3 2

3 4 3

4 5 2

1 4 1

【样例输出】

5

3

#include<bits/stdc++.h>
using namespace std;
/*
5 6
1
2
3
4
5
1 2 5
2 5 1
1 3 2
3 4 3
4 5 2
1 4 1
*/
#define M 10005
#define inf 100000000
int ding[110];
int n,m;
typedef struct Node
{
	int id;
	int w;
}node,*adj;

vector<adj>L[M];  //vector数组实现邻接表 
int dist[M];
bool visit[M];

int Find()
{
	int mini=-1,min=inf;
	for(int i=0;i<n;i++)
	{
		if(!visit[i]&&dist[i]<min)
		{
			mini=i;
			min=dist[i];
		}
	}
	return mini;
}

void Dijkstra()   
{
	for(int j=1;j<=n;j++) //初始化 
	{
		dist[j]=inf;
		visit[j]=false;
	}
	dist[1]=0;
	while(true)  
	{
		int mini=Find();//找离已经确定的最短路径最近的结点 
		if(mini==-1) break;
		
		visit[mini]=true;
		int len=L[mini].size();
		for(int j=0;j<len;j++)//判断该点受影响的邻接点 
		{
			int t=L[mini][j]->id;
			if(!visit[t] && (dist[mini]+L[mini][j]->w < dist[t]))
			{
				dist[t]=dist[mini]+L[mini][j]->w;
			}
		}
	} 	
}

int main()
{
	cin>>n>>m;
	for(int i=1;i<=n;i++)
	{
		cin>>ding[i];
	}
	for(int i=1;i<=m;i++)
	{
		int u,v,w;
		//cin>>u>>v>>w;
		scanf("%d %d %d",&u,&v,&w);
		if(u==v) continue;
		adj a=new node;  //无向图,两个顶点都要进行操作 
		a->id=v;
		a->w=w;
		L[u].push_back(a);
		
		adj b=new node;
		b->id=u;
		b->w=w;
		L[v].push_back(b);
	}
	Dijkstra();
	
	for(int j=2;j<=n;j++)   
	{                        
		cout<<dist[j]<<endl;
	}
	return 0;
}

3. 布线问题

【问题描述】

印刷电路板将布线区域划分成n*m个方格阵列,精确的电路布线问题要求确定连接方格a的中点到方格b的中点的最短布线问题。在布线时,电路只能沿着直线或直角布线。为了避免线路相交,已布了线的方格做了封锁标记,其他线路不允许穿过被封锁的方格。

【输入形式】输入共有n+3行
第一行包括两个数,n,m表示电路板是一个n*m的方格阵列
第二行包括两个数,row1,col1,表示起始点的行号和列号
第三行包括两个数,row2,col2,表示目标点的行号和列号
然后输入n行,每行m个数,0或1,表示电路板的封锁情况,1表示电路封锁

【输出形式】输出只有一行
表示从起始点到目的点的最短距离(第1步在起始点,输出到达目标点的步数)

【样例输入】

10 10
1 1

3 4

0 0 0 0 0 0 0 0 0 0

0 0 0 1 0 0 0 0 0 0

0 1 1 1 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 0 0

0 0 0 0 0 0 0 0 0 0

【样例输出】

8

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

int n,m;
int r1,c1,r2,c2;
int dx[4]={0,1,0,-1},dy[4]={1,0,-1,0};
int d[101][101];
int ans=1e9+10,maxx=1;

void dfs(int x,int y)
{
	if(x==r2 && y==c2)
	{
		ans=min(ans,maxx);
		return ;
	}
	for(int i=0;i<4;i++)
	{
		int xx=x+dx[i],yy=y+dy[i];
		if(d[xx][yy]==0 && maxx+1<=ans && xx>=0 && xx<=n && yy>=0 && yy<=m)
		{
			maxx++;
			d[xx][yy]=1;
			dfs(xx,yy);
			maxx--;
			d[xx][yy]=0;
		}
	}	
}	

int main()
{
    cin>>n>>m;
    cin>>r1>>c1>>r2>>c2;
    for(int i=0;i<n;i++)
    {
    	for(int j=0;j<m;j++)
    	{
    		cin>>d[i][j];
		}
	}
    dfs(r1,c1);
    cout << ans;
    return 0;
}

4. 最小重量机器设计

【问题描述】

问题描述:设某一机器由n个部件组成,每一种部件都可以从m个不同的供应商处购得。设 wij是从供应商j处购得的部件 i 的重量, cij 是相应的价格。试设计一个优先队列式分支限界法算法,试设计一个算法,给出总价格不超过d的最小重量机器设计。

【输入形式】

第一行有3个正整数n , m , d 。接下来的2n 行,每行n个数。前n行是c ,后n 行是w

【输出形式】

最小重量及每个部件的供应商

【样例输入】

8 18 14
18 15 20 5 15 10 16 6 1 6 17 6 1 2 17 15 13 17
16 6 7 4 7 2 11 6 18 4 13 12 8 5 2 8 15 14
12 6 19 10 13 8 2 10 16 4 15 15 16 13 17 12 14 4
18 18 2 13 15 19 5 12 18 7 13 9 8 17 10 13 15 11
8 5 14 11 18 20 17 3 11 17 13 11 4 9 17 14 19 1
10 7 8 11 13 3 19 3 12 11 12 14 4 2 12 10 14 15
12 9 13 9 16 17 12 15 6 3 11 17 13 17 14 13 4 4
19 12 3 19 3 20 19 12 8 19 8 10 19 20 3 1 7 1
16 12 4 16 2 6 15 1 13 3 7 16 5 3 16 16 14 19
12 14 6 2 11 15 9 17 15 16 19 20 14 14 20 9 4 4
6 13 16 6 3 12 12 19 11 20 4 13 9 18 7 17 8 1
4 17 3 20 3 8 12 7 4 12 6 12 1 18 13 20 20 8
4 15 1 10 2 12 8 11 5 4 20 13 12 20 1 3 3 11
1 9 2 1 16 1 12 4 5 2 7 15 12 3 9 4 13 6
13 1 10 8 5 13 20 10 6 4 8 15 8 8 20 11 9 9
2 10 11 1 18 8 20 11 18 2 3 6 14 16 19 4 3 15

【样例输出】

57
13 6 7 3 18 14 10 16

#include<bits/stdc++.h>
using namespace std;
const int M=1000;
int n,m,d;
int c[M][M],w[M][M];
int x[M],bestx[M];
int cw=0,cp=0;
int bestw=1e4,bestp=1e4;

void dfs(int t)
{
	if(t>n)
	{
		if(cp<=d && cw<bestw)
		{
			bestw=cw;
			bestp=cp;
			for(int i=1;i<=n;i++)
			{
				bestx[i]=x[i];
			}
		}
	}
	else
	{
		for(int i=1;i<=m;i++)
		{
			x[t]=i;
			cw+=w[t][i];
			cp+=c[t][i];
			if(cp<=d&&cw<bestw)
			{
				dfs(t+1);
			}
			cw-=w[t][i];
			cp-=c[t][i];
		}
	}
}

int main()
{
	cin>>n>>m>>d;
	for(int i=1;i<=n;i++)
	{
		for(int j=1;j<=m;j++)
		{
			cin>>c[i][j];
		}
	}
	for(int i=1;i<=n;i++)
	{
		for(int j=1;j<=m;j++)
		{
			cin>>w[i][j];
		}
	}
	dfs(1);
	cout <<bestw<<endl;
	for(int i=1;i<=n;i++)
	{
		cout << bestx[i]<<" ";
	}
	return 0;
} 

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值