アルゴリズム設計
問題の説明
n 人に割り当てて実行する必要があるタスクが n (n ≥ 1) あり、各タスクは 1 人にのみ割り当てることができ、各人が実行できるタスクは 1 つだけです。
i 番目の人が j 番目のタスクを実行するためのコストは c[i][j] (1≤i, j≤n) です。総コストを最小限に抑える配分計画を見つける
問題解決のアイデア
バックトラック問題解決の一般的な手順
(1) 特定の問題に対する問題の解空間ツリーを決定する 問題の解空間ツリーには、問題の少なくとも 1 つの解または最適解が含まれている必要があります。
(2) ノードの拡張検索ルールを決定します。
(3) 解空間ツリーを深さ優先で検索し、検索プロセス中の無効な検索を回避するために分岐削減機能を使用します。このうち、深さ優先法では、再帰的バックトラッキングまたは反復的(非再帰的)バックトラッキングを選択できます。
問題を適切に変換すると、順列ツリーとして解空間ツリーが得られ、このツリー内の各完全なパスが可能な解を表します。ツリーを深さ優先で検索し、考えられるすべての解決策を列挙し、最小コストの結果を見つけます。その中には、不可能な解を削除する制約関数が構築されており、プログラムの効率が大幅に向上します。
アルゴリズムの説明
(1) 解決空間
解決空間は {x1, x2, x3, x4..., xn} (xi=1, 2, 3, 4...n) であり、i 人目
( 2) 解空間ツリー
#include<iostream>
#include<cstring>
using namespace std;
#define MAXN 20
#define INF 9999
//定义问题
int n=4;
int a[MAXN][MAXN]={
{
0,0,0,0,0},{
0,9,2,7,8},{
0,6,4,3,7},{
0,5,8,1,8},{
0,7,6,9,4}};
//存储结果
int temp[MAXN]; //临时解
int temp_cost=0; //临时成本
int best[MAXN]; //最优解
int best_cost=INF; //最优成本
bool worker[MAXN]; //任务是否分配
//深度优先遍历算法
void dfs(int i)
{
if(i>n) //遍历到叶子节点
{
if(temp_cost<best_cost) //临时成本<最优成本
{
best_cost=temp_cost; //更新最优成本
for(int j=1;j<=n;j++)
best[j]=temp[j]; //更新最优解
}
}
else
{
for(int j=1;j<=n;j++) //遍历任务
if(!worker[j]) //如果任务没有被选择,执行以下语句
{
worker[j]=true; //任务被选择
temp[i]=j; //j任务分配给i人员
temp_cost+=a[i][j]; //临时成本
dfs(i+1); //下一个人员分配任务 执行dfs(2),判断worker[1]=true已经被分配,执行j=2,第2个任务分配,直到i=4分配完成
worker[j]=false; // ①执行worker[4]=false ②
temp[j]=0; //①temp[4]=0
temp_cost=temp_cost-a[i][j]; //①减去第四个人员成本
}
}
}
int main()
{
memset(worker,0,sizeof(worker));//worker初始化为false
dfs(1); //从人员1开始
for(int k=1;k<=n;k++)
printf("第%d个人安排任务%d\n",k,best[k]);
printf("总成本%d\n",best_cost);
return 0;
}