1 条题解

  • 0
    @ 2025-5-12 19:23:53

    题意分析

    题意分析

    这道题目描述的是一个商品配送优化问题,我们需要将多个供应点的商品合理分配给多个店主,使得总运输成本最小。具体条件如下:

    1. 商品种类:共有 KK 种商品,每种商品的需求和供应需要分别计算。
    2. 店主需求NN 个店主,每个店主对每种商品的需求量为 order[i][k]order[i][k]ii 是店主编号,kk 是商品种类)。
    3. 供应点库存MM 个供应点,每个供应点对每种商品的库存为 supply[j][k]supply[j][k]jj 是供应点编号,kk 是商品种类)。
    4. 运输成本:对于第 kk 种商品,从供应点 jj 运送到店主 ii 的单位成本为 cost[k][i][j]cost[k][i][j]
    5. 目标:检查是否可以满足所有店主的所有商品需求,如果可以,则计算最小运输成本;否则返回 1-1

    解题思路

    一开始是把所有商家的每种物品和所有供应商所有物品连边跑费用流,但很麻烦,因为这样建出来的图,边数会非常的庞大。那么其实转化一下思路,每种物品之间是不会互相影响的,那么把每种物品求出来后,累加起来就是答案了。

    C++代码实现

    #include <cstdio>
    #include <cstring>
    #include <iostream>
    #include <algorithm>
    #include <queue>
    #include <vector>
    #include <cmath>
    #define min(a,b)    (((a) < (b)) ? (a) : (b))
    #define max(a,b)    (((a) > (b)) ? (a) : (b))
    #define abs(x)    ((x) < 0 ? -(x) : (x))
    #define INF 0x3f3f3f3f
    #define delta 0.85
    using namespace std;
    
    #define MAX_V 105
    struct edge{
    	int to, cap, cost, rev;
    	edge(int to, int cap, int cost, int rev):to(to), cap(cap), cost(cost), rev(rev){}
    };
    
    int V;
    vector<edge> G[MAX_V];
    int h[MAX_V], dist[MAX_V];
    int prevv[MAX_V], preve[MAX_V];
    
    void add_edge(int from, int to, int cap, int cost){
    	G[from].push_back(edge(to, cap, cost, G[to].size()));
    	G[to].push_back(edge(from, 0, -cost, G[from].size() - 1));
    }
    
    int min_cost_flow(int s, int t, int f){
    	int res = 0;
    	memset(h, 0, sizeof(h));
    	
    	while(f > 0){
    		// Dijkstra
    		priority_queue<pair<int, int>, vector<pair<int, int> >, greater<pair<int, int> > > que;
    		memset(dist, 0x3f, sizeof(dist));
    		dist[s] = 0;
    		que.push(pair<int, int>(0, s));
    		while(!que.empty()){
    			pair<int, int> p = que.top(); que.pop();
    			int v = p.second;
    			if(dist[v] < p.first) continue;
    			for(int i = 0; i < G[v].size(); i++){
    				edge &e = G[v][i];
    				int d2 = dist[v] + e.cost + h[v] - h[e.to];
    				if(e.cap > 0 && d2 < dist[e.to]){
    					dist[e.to] = d2;
    					prevv[e.to] = v;
    					preve[e.to] = i;
    					que.push(pair<int, int>(dist[e.to], e.to));
    				}
    			}
    		}
    		if(dist[t] == INF){
    			return -1;
    		}
    		for(int v = 0; v < V; v++) h[v] += dist[v];
    		int d = f;
    		for(int v = t; v != s; v = prevv[v]){
    			d = min(d, G[prevv[v]][preve[v]].cap);
    		}
    		f -= d;
    		res += d * h[t];
    		for(int v = t; v != s; v = prevv[v]){
    			edge &e = G[prevv[v]][preve[v]];
    			e.cap -= d;
    			G[v][e.rev].cap += d;
    		}
    	}
    	return res;
    }
    
    void clear_graph(){
    	for(int v = 0; v < V; v++) G[v].clear();
    }
    
    #define MAX_N 50
    int N, M, K, F;
    int cost[MAX_N][MAX_N][MAX_N];
    int od[MAX_N][MAX_N], sg[MAX_N][MAX_N];
    int ods[MAX_N], sgs[MAX_N];
    
    void solve(){
    	int res = 0;
    	for(int k = 0; k < K; k++){
    		// 物品 k 存货小于需求
    		if(ods[k] > sgs[k]){
    			printf("-1\n");
    			return;
    		}
    		// 初始化图
    		int s = N + M, t = s + 1;
    		V = t + 1, F = ods[k];
    		clear_graph();
    		// 建图
    		for(int i = 0; i < N; i++) add_edge(s, i, od[i][k], 0);
    		for(int i = 0; i < M; i++) add_edge(N + i, t, sg[i][k], 0);
    		for(int i = 0; i < N; i++){
    			for(int j = 0; j < M; j++){
    				add_edge(i, N + j, INF, cost[k][i][j]);
    			}
    		}
    		res += min_cost_flow(s, t, F);
    	}
    	
    	printf("%d\n", res);
    }
    
    int main(){
    	while(~scanf("%d%d%d", &N, &M, &K) && (N | M | K)){
    		memset(ods, 0, sizeof(ods));
    		memset(sgs, 0, sizeof(sgs));
    		for(int i = 0; i < N; i++){
    			for(int k = 0; k < K; k++){
    				scanf("%d", &od[i][k]);
    				ods[k] += od[i][k];
    			}
    		}
    		for(int i = 0; i < M; i++){
    			for(int k = 0; k < K; k++){
    				scanf("%d", &sg[i][k]);
    				sgs[k] += sg[i][k];
    			}
    		}
    		for(int k = 0; k < K; k++){
    			for(int i = 0; i < N; i++){
    				for(int j = 0; j < M; j++){
    					scanf("%d", &cost[k][i][j]);
    				}
    			}
    		}
    		solve();
    	}
    	return 0;
    }
    
    
    • 1

    信息

    ID
    1517
    时间
    1000ms
    内存
    256MiB
    难度
    10
    标签
    递交数
    2
    已通过
    1
    上传者