设有n件工作分配给n个人。将工作i分配给第j个人所需的费用为cij 。 设计一个算法,对于给定的工作费用,为每一个人都分配1 件不同的工作,并使总费用达到最小。

设有n件工作分配给n个人。将工作i分配给第j个人所需的费用为cij 。 设计一个算法,对于给定的工作费用,为每一个人都分配1 件不同的工作,并使总费用达到最小。

输入格式:
输入数据的第一行有1 个正整数n (1≤n≤20)。接下来的n行,每行n个数,表示工作费用。

输出格式:
将计算出的最小总费用输出到屏幕。

输入样例:
在这里给出一组输入。例如:

3
10 2 3
2 3 4
3 4 5
输出样例:
在这里给出相应的输出。例如:

9

#include<iostream>
#include<climits>
using namespace std;
#define N 21
int cost[N][N];
int a[N];
int n,cv;
int bestv=INT_MAX;
void backtrack(int t)
{
        if(t>n)
        {
                if(cv<bestv)
                        bestv=cv;
                return;
        }
        else
        {
                for(int i=t;i<=n;i++)
                {
                        cv+=cost[t][a[i]];
                        swap(a[t],a[i]);
                        if(cv < bestv)
                                backtrack(t+1);
                        swap(a[t],a[i]);
                        cv-= cost[t][a[i]];
                }
        }
}
 
int main()
{
        int i,j;
        while(cin>>n)
        {
                for(i=1;i<=n;i++)
                        for(j=1;j<=n;j++)
                                cin>>cost[i][j];
                for(i=1;i<=n;i++)
                        a[i]=i;
                backtrack(1);
                cout<<bestv<<endl;
        }
        return 0;
}
  • 4
    点赞
  • 25
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
### 回答1: 这是一个经典的任务分配问题,可以使用匈牙利算法来解决。首先,我们将每个人看作一个节点,每个工作看作一个节点,然后建立一个二分图。对于每个工作节点i,与每个人节点j之间连一条边,边权为cij。然后,我们从任意一个未匹配的人节点开始,尝试将其与一个未匹配的工作节点匹配。如果匹配成功,则继续尝试为下一个未匹配的人节点寻找匹配。如果匹配失败,则尝试调整已匹配的人节点的匹配,使其可以匹配到其他工作节点。重复这个过程,直到所有人节点都被匹配。最终,所有人都会被分配到一不同工作,并且总费用达到最小。 ### 回答2: 这是一个非常典型的任务分配问题,可以用匈牙利算法解决。具体算法流程如下: 1. 定义一个长度为n的数组match,用来记录每个人分配工作编号,初始值均为-1。 2. 对于每个人i,从未分配工作工作中,选取一与其费用最小工作j,尝试将i与j匹配。具体实现中,可以用一个长度为n的数组used记录哪些工作已被匹配过,初始值均为false。 3. 若工作j未被匹配,则直接匹配;否则,将以前匹配了这个工作的人k暂时从工作中删除,然后尝试将当前人i与工作j匹配,接着再把k与原来的工作匹配。 4. 若i与j匹配成功,则将match[i]赋值为j,并返回true;否则返回false,表示无法分配更小的费用。 5. 重复步骤2-4,直到每个人分配了一工作为止。 6. 最终返回所有匹配成功的费用的总和。 算法的时间复杂度为O(n^3),可以通过优化达到O(n^2)。实际应用中,任务分配问题经常涉及到多个限制条和优化目标,可能要使用更高级的算法来解决,例如线性规划、整数规划、遗传算法等。 ### 回答3: 这个问题可以通过使用匈牙利算法来解决。这是一个经典的图匹配问题,其中每个工作被视为左边的一个节点,每个人被视为右边的一个节点,每个费用被视为一条连接左边和右边节点的边。 匈牙利算法的基本思想是,首先将所有人设为未匹配状态。接下来,对于每个未匹配的人,尝试将其分配一个工作上。对于每个未分配工作,找到一个可以与该人匹配的工作,并更新匹配状态以反映该匹配。如果找不到可匹配的工作,则将该人从未匹配状态转移到匹配状态,然后继续处理下一个未匹配的人,直到所有人都被匹配。 为了实现这个算法,我们可以使用一个二维数组来存储费用一个一维数组来存储每个人的状态,以及一个额外的数组来记录每个工作的匹配状态。 以下是一个示例实现: ``` // n为人数,c为费用数组,match为匹配状态数组 int hungarian(int n, int c[][n], int match[]) { // 初始化未匹配状态 int lx[n], ly[n], slack[n], prev[n]; memset(ly, 0, sizeof(ly)); for (int i = 0; i < n; i++) { lx[i] = INT_MIN; for (int j = 0; j < n; j++) { if (c[i][j] > lx[i]) { lx[i] = c[i][j]; } } } memset(match, -1, sizeof(int) * n); // 匈牙利算法 for (int i = 0; i < n; i++) { memset(slack, 0x7f, sizeof(slack)); int u = i, v = -1; while (v == -1) { int min_slack = INT_MAX, min_j; for (int j = 0; j < n; j++) { if (match[j] == -1) { if (lx[u] + ly[j] - c[u][j] < slack[j]) { slack[j] = lx[u] + ly[j] - c[u][j]; prev[j] = u; } if (slack[j] < min_slack) { min_slack = slack[j]; min_j = j; } } } for (int j = 0; j < n; j++) { if (ly[j] < min_slack) { min_slack = ly[j]; min_j = -1; } } if (min_j == -1) { int delta = INT_MAX; for (int j = 0; j < n; j++) { if (match[j] == -1 && slack[j] < delta) { delta = slack[j]; } } for (int j = 0; j < n; j++) { if (lx[prev[j]] + ly[j] == c[prev[j]][j] && slack[j] == delta) { if (match[j] != -1) { prev[match[j]] = j; v = match[j]; } else { v = j; } match[j] = prev[j]; break; } } } else { if (match[min_j] == -1) { v = min_j; } else { prev[match[min_j]] = min_j; v = match[min_j]; } match[min_j] = u; } } while (u != -1) { int nxt = match[u]; ly[u] += lx[u] - c[u][nxt]; lx[nxt] = max(lx[nxt], lx[u] - ly[u] + c[u][nxt]); u = prev[u]; } } // 计算总费用 int cost = 0; for (int i = 0; i < n; i++) { cost += c[match[i]][i]; } return cost; } ``` 请注意,该算法的复杂度为O(n^3),因此只适用于较小的问题规模。对于较大的问题,可以使用其他算法,如KM算法
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值