Minimum Cost

 

Description

Dearboy, a goods victualer, now comes to a big problem, and he needs your help. In his sale area there are N shopkeepers (marked from 1 to N) which stocks goods from him.Dearboy has M supply places (marked from 1 to M), each provides K different kinds of goods (marked from 1 to K). Once shopkeepers order goods, Dearboy should arrange which supply place provide how much amount of goods to shopkeepers to cut down the total cost of transport.        

It's known that the cost to transport one unit goods for different kinds from different supply places to different shopkeepers may be different. Given each supply places' storage of K kinds of goods, N shopkeepers' order of K kinds of goods and the cost to transport goods for different kinds from different supply places to different shopkeepers, you should tell how to arrange the goods supply to minimize the total cost of transport.      

Input

The input consists of multiple test cases. The first line of each test case contains three integers N, M, K (0 < N, M, K < 50), which are described above. The next N lines give the shopkeepers' orders, with each line containing K integers (there integers are belong to [0, 3]), which represents the amount of goods each shopkeeper needs. The next M lines give the supply places' storage, with each line containing K integers (there integers are also belong to [0, 3]), which represents the amount of goods stored in that supply place.        

Then come K integer matrices (each with the size N * M), the integer (this integer is belong to (0, 100)) at the i-th row, j-th column in the k-th matrix represents the cost to transport one unit of k-th goods from the j-th supply place to the i-th shopkeeper.        

The input is terminated with three "0"s. This test case should not be processed.       

Output

For each test case, if Dearboy can satisfy all the needs of all the shopkeepers, print in one line an integer, which is the minimum cost; otherwise just output "-1".      

Sample Input

1 3 3   
1 1 1
0 1 1
1 2 2
1 0 1
1 2 3
1 1 1
2 1 1

1 1 1
3
2
20

0 0 0

Sample Output

4
-1

 

这个题意就是有n(商店),m(提供商),k(商品),然后接着分别输入n*k,代表每个商店所需要的k商品的数量,然后是m*k代表的是每个提供商拥有的k商品的个数,接着是k个n*m,代表每个商品由提供商到商店所需的消耗,所以这个题就是让求最小的耗费,这个题要把k个商品分开来求,最后再求和。建图方式注释详见

#include <iostream>
#include<stdio.h>
#include<string.h>
#include<stdlib.h>
#include<math.h>
#define oo 1<<28
#include<queue>
#include<algorithm>
using namespace std;
int pre[210000];
int dis[210000];
int vist[210000];
int head[210000];
int a[100000],b[100000];
int need[1000][1000],have[1000][1000],money[500][500][500];
struct node
{
    int u;
    int v;//与u点相连的点
    int f;//容量
    int w;//权值
    int next;//下一条边
} edge[1100000];
int cnt=0;
int s,t;
void add(int u,int v,int f,int w)
{
    edge[cnt].u=u;
    edge[cnt].v=v;
    edge[cnt].f=f;
    edge[cnt].w=w;
    edge[cnt].next=head[u];
    head[u]=cnt++;

    edge[cnt].u=v;
    edge[cnt].v=u;
    edge[cnt].f=0;
    edge[cnt].w=-w;//反向的权值为正向的相反数
    edge[cnt].next=head[v];
    head[v]=cnt++;
}
void init()
{
    memset(pre,-1,sizeof(pre));
    memset(vist,0,sizeof(vist));
    for(int i=0; i<=t; i++)
    {
        dis[i]=oo;
    }
}
int spfa()
{
    int i;
    init();
    queue<int>q;
    dis[s]=0;
    vist[s]=1;
    q.push(s);
    while(!q.empty())//将相邻点进行松弛,直到队列为空
    {
        int u=q.front();//取出队头
        q.pop();
        i=head[u];
        vist[u]=0;
        while(i!=-1)
        {
            int w=edge[i].w;
            int v=edge[i].v;
            if(edge[i].f>0&&dis[v]>dis[u]+w)//判断是否可以更新
            {
                dis[v]=dis[u]+w;//改进s到v点的值
                pre[v]=i;//记录此点的前驱
                if(!vist[v])//由于距离变小了,如果v点松弛成功且v点不在队列里,因为v点有可能还能改进别的点
                {
                    vist[v]=1;
                    q.push(v);
                }
            }
            i=edge[i].next;
        }
    }
    if(pre[t]==-1)//如果不在最短路中代表寻找失败
        return 0;
    return 1;
}
int Cost()
{
    int ans=0;
    while(spfa())//如果增广路寻找成功
    {
        int maxx=oo;
        int p=pre[t];//初始化P指针
        while(p!=-1)
        {
            maxx=min(edge[p].f,maxx);//求出此增广路上边的最小值
            p=pre[edge[p].u];
        }
        p=pre[t];
        while(p!=-1)
        {
            edge[p].f-=maxx;//正向减去
            edge[p^1].f+=maxx;//反向增加
            ans+=maxx*edge[p].w;//因为以单位计费,所以应当乘上流量
            p=pre[edge[p].u];
        }
    }
    return ans;
}
int main()
{
    int n,m,d,k;
    int i,j,l;
    while(~scanf("%d%d%d",&n,&m,&k),n||m||k)
    {
        int u,v,w;
        memset(a,0,sizeof(a));
        memset(b,0,sizeof(b));
        for(i=1; i<=n; i++)
        {
            for(j=1; j<=k; j++)
            {
                scanf("%d",&need[j][i]);
                a[j]+=need[j][i];//每个商品商店一共需要多少
            }
        }
        for(i=1; i<=m; i++) //每一个货物
        {
            for(j=1; j<=k; j++)
            {
                scanf("%d",&have[j][i]);
                b[j]+=have[j][i];//每个商品提供商一共拥有多少
            }
        }
        for(i=1; i<=k; i++)
        {
            for(j=1; j<=n; j++)
            {
                for(l=1; l<=m; l++)
                {
                    scanf("%d",&money[i][l][j]);//第k件物品由运货商到商店需要的代价
                }
            }
        }
        int flag=1;
        for(i=1;i<=k;i++)
        {
            if(b[i]<a[i])//若k种商品提供商拥有的比需要量小
            {
                flag=0;
                break;//则直接退出,因为k种商品不满足
            }
        }
        if(flag==0)
        {
            printf("-1\n");
        }
        else
        {
            int sum=0;
            
            for(i=1;i<=k;i++)//分成k个商品分别求最小费用
            {
                memset(head,-1,sizeof(head));
                for(j=1;j<=m;j++)
                {
                    add(0,j,have[i][j],0);//将源点和运货商连,容量为第i种物品第j个运销商所拥有个个数,权值为0
                }
                for(j=1;j<=n;j++)
                {
                    add(j+m,m+n+1,need[i][j],0);//将商店和汇点相连,容量为第i种物品第j个商品所需要的个数,权值为0
                }
                for(j=1;j<=m;j++)
                {
                    for(l=1;l<=n;l++)
                    {
                        add(j,l+m,oo,money[i][j][l]);//将运销商和商店连,容量为无穷,因为不知多大,权值为第i件物品第j个运销商到第l个商店所需要费用
                    }
                }
                s=0,t=n+m+1;
                int e=Cost();
                sum+=e;
            }
            printf("%d\n",sum);
        }
    }
    return 0;
}


 

【无人机】基于改进粒子群算法的无人机路径规划研究[和遗传算法、粒子群算法进行比较](Matlab代码实现)内容概要:本文围绕基于改进粒子群算法的无人机路径规划展开研究,重点探讨了在复杂环境中利用改进粒子群算法(PSO)实现无人机三维路径规划的方法,并将其与遗传算法(GA)、标准粒子群算法等传统优化算法进行对比分析。研究内容涵盖路径规划的多目标优化、避障策略、航路点约束以及算法收敛性和寻优能力的评估,所有实验均通过Matlab代码实现,提供了完整的仿真验证流程。文章还提到了多种智能优化算法在无人机路径规划中的应用比较,突出了改进PSO在收敛速度和全局寻优方面的优势。; 适合人群:具备一定Matlab编程基础和优化算法知识的研究生、科研人员及从事无人机路径规划、智能优化算法研究的相关技术人员。; 使用场景及目标:①用于无人机在复杂地形或动态环境下的三维路径规划仿真研究;②比较不同智能优化算法(如PSO、GA、蚁群算法、RRT等)在路径规划中的性能差异;③为多目标优化问题提供算法选型和改进思路。; 阅读建议:建议读者结合文中提供的Matlab代码进行实践操作,重点关注算法的参数设置、适应度函数设计及路径约束处理方式,同时可参考文中提到的多种算法对比思路,拓展到其他智能优化算法的研究与改进中。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值