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
2
1
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;
}