分配问题

题目链接

题目描述

有n件工作要分配给n个人做.第i个人做第j件工作产生的效益为 C i j C_{ij} Cij.试设计一个将n件工作分配给n个人做的分配方案,使产生的总效益最大.

输入格式

文件的第1行有1个正整数n,表示有n件工作要分配给n个人做.
接下来的n行中,每行有n个整数 C i j C_{ij} Cij,表示第i个人做第j件工作产生的效益为 C i j C_{ij} Cij.

输出格式

两行分别输出最小总效益和最大总效益。

输入输出样例

样例输入
5
2 2 2 1 2
2 3 1 2 4
2 0 1 1 1
2 3 4 3 3
3 2 1 2 1
样例输出
5
14

说明/提示

1 ≤ \le n ≤ 100 \le100 100
一个人只能修一个工件

这是一道费用流经典题目

建图

  • 1.0超级源点2 × \times ×n+1超级汇点,第i个人的节点为i,第j件工作节点为j+n
  • 2.超级源点 ∀ \forall i ∈ \in [1,n]连接一条容量为1,费用为0的边
  • 3. ∀ \forall j ∈ \in [n+1,2 × \times ×n]向超级汇点连接一条容量为1,费用为 0 0 0的边
  • 4.从 ∀ \forall i ∈ \in [1, n]向 ∀ \forall j ∈ \in [n+1,n × \times × 2],连接一条容量为1,费用为 C i , j C_{i, j} Ci,j的边

做法

跑一遍最小费用最大流&最大费用最小流,然后再分别输出最值与最
(温馨提醒:一定要输出,不然会WA!)

为各位大佬献上我丑陋的代码~

#include<bits/stdc++.h>
#define FQ(i,a,b) for(register int i=a;i<=b;i++)
#define prf printf
#define scf scanf
#define ll long long
using namespace std;
const int N=5e4+10;
int INF,n,num=1,ne[N],fi[N],to[N],w[N],pl[N],S,T;
int dst[N],incf[N],P[N],vis[N],ans;
queue<int> q;
void FindMaxN()
{
	int fINDmAXn[1];
	memset(fINDmAXn,128/2,sizeof(fINDmAXn));	
	INF=fINDmAXn[0];
}
ll read()
{
	ll x=0,f=1;char ch=getchar();
	while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();}
	while(ch>='0'&&ch<='9'){x=x*10+ch-'0';ch=getchar();}
	return x*f;	
}
void add(int x,int y,int z,int kl)
{
    ne[++num]=fi[x];    
    fi[x]=num;    
    to[num]=y;   
    w[num]=z;
    pl[num]=kl; 
}
bool spfa()
{ 
    for(int i=S;i<=T;i++)dst[i]=INF; 
    memset(vis,0,sizeof(vis));  
    q.push(S),dst[S]=0;	
	incf[S]=1<<30,vis[S]=true;   
    while(!q.empty())
    {      
        int x=q.front();      
        vis[x]=false;q.pop();        
        for(int i=fi[x];i;i=ne[i])
        {            
            int ver=to[i];             
            if(dst[ver]>dst[x]+pl[i]&&w[i])
            {                
                dst[ver]=dst[x]+pl[i];                
                incf[ver]=min(incf[x],w[i]);                
                P[ver]=i;                
                if(!vis[ver])vis[ver]=true,q.push(ver);                 
            }             
        }    
    }
    return dst[T]!=INF;  
}
void update()
{	
	int x=T;     
    while(x!=S)
    {         
        int i=P[x];         
        w[i]-=incf[T];       
        w[i^1]+=incf[T];
   
        x=to[i^1];
    }
    ans+=dst[T]*incf[T];
}
bool spfa_d()
{
    for(int i=S;i<=T;i++)dst[i]=-INF;
    q.push(S),dst[S]=0;incf[S]=1<<30;
    while(!q.empty())
    {
        int x=q.front();
        vis[x]=false;q.pop();
        for(int i=fi[x];i;i=ne[i])
        {
            int ver=to[i];
            if(dst[ver]<dst[x]+pl[i]&&w[i])
            {
                dst[ver]=dst[x]+pl[i];
                incf[ver]=min(incf[x],w[i]);
                P[ver]=i;
                if(!vis[ver])vis[ver]=true,q.push(ver);
            }
        }
    }
    return dst[T]!=-INF;
}
void update_d()
{
	int x=T;
    while(x!=S)
    {
        int i=P[x];
        w[i]-=incf[T];
        w[i^1]+=incf[T];
        x=to[i^1];
    }
    ans+=dst[T]*incf[T];
}
void add_x(int x,int y,int z,int kl)
{
	add(x,y,z,kl);
	add(y,x,0,-kl);
}
int main()
{
	//freopen(".in","r",stdin);
	//freopen(".out","w",stdout);
	FindMaxN();
	n=read();S=0,T=n*2+1;
	for(int i=1;i<=n;i++)
	{
		for(int j=1;j<=n;j++)
		{
			int x=read();
			add_x(i,j+n,1,x);
		}
	}
	for(int i=1;i<=n;i++)add_x(S,i,1,0),add_x(i+n,T,1,0);
	while(spfa())update();
	printf("%d\n",ans);
	ans=0;
	for(int i=2;i<=num;i+=2)w[i]+=w[i^1],w[i^1]=0;
	while(spfa_d())update_d();
	printf("%d\n",ans);
	return 0;		
}
//**月雩·薇嫭**
by:月雩·薇嫭
在多无人机协同作业中,任务分配问题是一个重要的问题。Matlab可以通过整数线性规划(ILP)来解决任务分配问题。ILP是一种优化问题,其中变量是整数,目标函数和约束条件是线性的。在任务分配问题中,我们可以将每个任务分配给一个无人机,并将每个无人机的状态(例如位置,速度等)作为变量。然后,我们可以将每个任务的需求(例如时间限制,资源需求等)作为约束条件。最终,我们可以通过求解ILP来找到最优的任务分配方案。 以下是一个简单的Matlab代码示例,用于解决任务分配问题: ```matlab % 定义任务和无人机数量 num_tasks = 5; num_drones = 3; % 定义任务需求和无人机状态 task_requirements = randi([1, 10], num_tasks, 1); drone_states = randi([1, 10], num_drones, 1); % 定义ILP变量和目标函数 f = reshape(repmat(task_requirements, 1, num_drones), [], 1); intcon = 1:num_tasks*num_drones; Aeq = kron(eye(num_tasks), ones(1, num_drones)); beq = ones(num_tasks, 1); lb = zeros(num_tasks*num_drones, 1); ub = ones(num_tasks*num_drones, 1); % 求解ILP x = intlinprog(f, intcon, [], [], Aeq, beq, lb, ub); % 将结果转换为任务分配矩阵 task_assignment = reshape(x, num_tasks, num_drones); % 显示任务分配矩阵 disp(task_assignment); ``` 该代码生成了5个任务和3个无人机的随机需求和状态。然后,它将ILP变量和目标函数定义为任务需求的重复和约束条件。最后,它使用Matlab的intlinprog函数来求解ILP,并将结果转换为任务分配矩阵。该矩阵显示了每个任务分配给哪个无人机。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值