1、工作分配问题![](https://i-blog.csdnimg.cn/blog_migrate/0bfa879e51f8bfe93cfbd2e78f4304b2.png)
#include <iostream>
#include <algorithm>
using namespace std;
const int N = 25;
int n;
int res, minres = 0x3f3f3f3f;
int g[N][N];
bool col[N];
void dfs(int u)
{
if(u >= n)
{
minres = min(minres, res);
return;
}
for(int i = 0; i < n; i++)
{
// 剪枝,一旦结果大于最小值,也就没有必要向下搜索
if(!col[i] && res < minres)
{
col[i] = true;
res += g[u][i];
dfs(u + 1);
// 恢复现场
col[i] = false;
res -= g[u][i];
}
}
}
int main()
{
cin >> n;
for(int i = 0; i < n; i++)
for(int j = 0; j < n; j++)
cin >> g[i][j];
dfs(0);
cout << minres << endl;
return 0;
}
2、布线问题
用样例解释一下题目吧!!
输出顺序表示每个元件放在哪个位置上。如(1,3,2):元件1在位置1,元件2在位置3,元件3在位置2。
3个元件,求出元件的一个排列顺序,使得此时布线长度最短。顺序(1,3,2),根据输入可知元件1、2之间有2条线,距离为3-1=2;元件1、3之间有3条线,距离为2-1=1;元件2、3之间有3条线,距离为3-2=1。所以总布线长度为。
这到题感觉其实是排列数字的进阶版。排列数字https://www.acwing.com/problem/content/844/
我的做法有点暴力,直接求出所有排列顺序,然后求出每次的总布线长度,求最小值。
我看其他有说分支限界法,这个我们才开始学,还不太懂,之后可能会优化一下代码。
#include <iostream>
#include <algorithm>
using namespace std;
const int N = 25;
int n;
int res, minres = 1e9; // res:记录每个分支的结果;minres:res中最小值即最终输出结果
int path[N], minpath[N]; // path:记录每个分支的顺序;minpath:最小分支顺序
int conn[N][N];
bool st[N];
/*
conn[a][b]:表示元件a,b之间的连接数。
path[i] = j表示:元件i在位置j;
*/
int cost() // 求总布线长度
{
int sum = 0;
// path[2] = 3表示:元件2在位置3
for(int i = 1; i <= n; i++)
for(int j = i + 1; j <= n; j++)
{
int a = path[i], b = path[j];
sum += conn[i][j] * abs(a - b);
}
return sum;
}
void dfs(int u) // 常规的深搜,求1~n的所有排列
{
if(u > n)
{
res = cost();
if(res < minres)
{
minres = res;
for(int i = 1; i <= n; i++) minpath[i] = path[i];
}
}
for(int i = 1; i <= n; i++)
{
// 可以剪枝,一旦结果大于最小值,也就没有必要向下搜索。但这里没有做
if(!st[i])
{
path[u] = i; // u元件在位置i
st[i] = true; // 标记位置i被用过
dfs(u + 1);
st[i] = false; // 恢复现场
}
}
}
int main()
{
cin >> n;
for(int i = 1; i <= n; i++)
for(int j = i + 1; j <= n; j++)
{
cin >> conn[i][j];
conn[j][i] = conn[i][j];
}
dfs(1);
cout << minres << endl;
for(int i = 1; i <= n; i++) cout << minpath[i] << ' ';
return 0;
}
对于代码中的所提到的问题,有知道的欢迎指正。