[pta]6-6 求解任务分配问题(回溯法)

有n(n≥1)个任务需要分配给n个人执行,每个任务只能分配给一个人,每个人只能执行一个任务。第i个人执行第j个任务的成本是c[i][j](1≤i,j≤n)。求出总成本最小的分配方案。

函数接口定义:

void dfs(int i)    ;

裁判测试程序样例:

#include <stdio.h>
#include <string.h>
#include <stdlib.h>
using namespace std;
#define INF 99999    //定义∞
#define MAXN 20
int n;
int c[MAXN][MAXN]={0};                           //下标0的元素不用
int x[MAXN];                    //临时解
int cost=0;                        //临时解的成本
int bestx[MAXN];                //最优解
int mincost=INF;                //最优解的成本
bool worker[MAXN];                //worker[j]表示任务j是否已经分配人员

void dfs(int i);

int main()
{    
   scanf("%d",&n);
   for(int i=1;i<=n;i++)
      for(int j=1;j<=n;j++)
          scanf("%d",&c[i][j]);
   memset(worker,0,sizeof(worker));    //worker初始化为false
   dfs(1);                //从人员1开始
   for (int k=1;k<=n;k++)
     printf("%d %d\n",k,bestx[k]);
   printf("%d",mincost);
   return 0;
}

/* 请在这里填写答案 */

输入格式:

第1行输入人数n。接下来输入n行,每行n个数,表示第i个人执行第j个任务的成本(w人员及任务编号从1到n)。

输出格式:

先输入分配方案:按人员编号递增顺序依次输出n行,每行两个数,分别表示人员编号和任务编号。最后再输出总成本

输入样例:

4
9 2 7 8
6 4 3 7
5 8 1 8
7 6 9 4

输出样例:

1 2
2 1
3 3
4 4
13

参考代码:

// 定义一个深度优先搜索函数,参数为当前处理的工人编号
void dfs(int i)
{
    // 如果当前处理的工人编号大于总工人数n
    if(i > n)
    {
        // 如果当前成本小于最小成本mincost
        if(mincost > cost)
        {
            // 更新最小成本mincost
            mincost = cost;
            // 将当前解x复制到最佳解bestx中
            for(int j=1;j<=n;j++)
            {
                bestx[j] = x[j];
            }
        }
    }
    else
    {
        // 遍历所有工人
        for(int j=1;j<=n;j++)
        {
            // 如果当前工人未被选中
            if(!worker[j])
            {
                // 标记当前工人为已选中
                worker[j] = true;
                // 将当前工人分配给第i个任务
                x[i] = j;
                // 更新当前成本
                cost = cost + c[i][j];
                // 继续处理下一个工人
                dfs(i+1);
                // 取消当前工人的选中状态
                worker[j] = false;
                // 将当前工人从第i个任务中移除
                x[i] = 0;
                // 恢复当前成本
                cost = cost - c[i][j];
            }
        }
    }
}

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值