订货 HYSBZ - 2424 最小费用最大流

某公司估计市场在第i个月对某产品的需求量为Ui,已知在第i月该产品的订货单价为di,上个月月底未销完的单位产品要付存贮费用m,假定第一月月初的库存量为零,第n月月底的库存量也为零,问如何安排这n个月订购计划,才能使成本最低?每月月初订购,订购后产品立即到货,进库并供应市场,于当月被售掉则不必付存贮费。假设仓库容量为S。

Input

第1行:n, m, S (0<=n<=50, 0<=m<=10, 0<=S<=10000)

第2行:U1 , U2 , ... , Ui , ... , Un (0<=Ui<=10000)

第3行:d1 , d2 , ..., di , ... , dn (0<=di<=100)

Output

只有1行,一个整数,代表最低成本

 

Sample Input

3 1 1000 2 4 8 1 2 4

Sample Output

34


设一个源点S,汇点t;

主要是建边的问题:

从 s 向每个月连一条 flow= inf , cost = di 的边,因为可以无限的进货,每次进货单价费用为 di;

每个月之间连 flow = s, cost = m 的边,总容量最大只能为仓库容量,而单位贮存费用为 m;

最后每个月再向 t 连 flow = ui, cost = 0 的边,因为需求量为 ui ,而销售的花费自然为0;

最后跑一遍 最小费用最大流即可;

#include<iostream>
#include<cstdio>
#include<algorithm>
#include<cstdlib>
#include<cstring>
#include<string>
#include<cmath>
#include<map>
#include<set>
#include<vector>
#include<queue>
#include<bitset>
#include<ctime>
#include<deque>
#include<stack>
#include<functional>
#include<sstream>
//#include<cctype>
//#pragma GCC optimize("O3")
using namespace std;
#define maxn 300005
#define inf 0x3f3f3f3f
#define INF 999999999999999
#define rdint(x) scanf("%d",&x)
#define rdllt(x) scanf("%lld",&x)
#define rdlf(x) scanf("%lf",&x)
#define rdstr(x) scanf("%s",x)
typedef long long  ll;
typedef unsigned long long ull;
typedef unsigned int U;
#define ms(x) memset((x),0,sizeof(x))
const long long int mod = 1e9 + 7;
#define Mod 20100403
#define sq(x) (x)*(x)
#define eps 1e-3
typedef pair<int, int> pii;
#define pi acos(-1.0)
const int N = 1005;
#define REP(i,n) for(int i=0;i<(n);i++)
inline ll rd() {
	ll x = 0;
	char c = getchar();
	bool f = false;
	while (!isdigit(c)) {
		if (c == '-') f = true;
		c = getchar();
	}
	while (isdigit(c)) {
		x = (x << 1) + (x << 3) + (c ^ 48);
		c = getchar();
	}
	return f ? -x : x;
}

ll gcd(ll a, ll b) {
	return b == 0 ? a : gcd(b, a%b);
}
ll sqr(ll x) { return x * x; }

bool vis[maxn];
int n, m, s, t;
int x, y, f, z;
int dis[maxn], pre[maxn], last[maxn], flow[maxn];
int maxflow, mincost;

struct node {
	int to, nxt, flow, cost;
}edge[maxn<<2];
int head[maxn], cnt;
queue<int>q;

void addedge(int from, int to, int flow, int cost) {
	edge[++cnt].to = to; edge[cnt].flow = flow; edge[cnt].cost = cost;
	edge[cnt].nxt = head[from]; head[from] = cnt;
}

bool spfa(int s, int  t) {
	memset(dis, 0x7f, sizeof(dis)); memset(flow, 0x7f, sizeof(flow));
	ms(vis);
	q.push(s); vis[s] = 1; dis[s] = 0; pre[t] = -1;
	while (!q.empty()) {
		int now = q.front(); q.pop(); vis[now] = 0;
		for (int i = head[now]; i != -1; i = edge[i].nxt) {
			int to = edge[i].to;
			if (edge[i].flow > 0 && dis[to] > dis[now] + edge[i].cost) {
				dis[to] = dis[now] + edge[i].cost;
				pre[to] = now; last[to] = i;
				flow[to] = min(flow[now], edge[i].flow);
				if (!vis[to]) {
					vis[to] = 1; q.push(to);
				}
			}
		}
	}
	return pre[t] != -1;
}

void maxflow_mincost() {
	while (spfa(s, t)) {
		int now = t;
		maxflow += flow[t]; mincost += flow[t] * dis[t];
		while (now != s) {
			edge[last[now]].flow -= flow[t];
			edge[last[now] ^ 1].flow += flow[t];
			now = pre[now];
		}
	}
}

int main()
{
	//ios::sync_with_stdio(false);
	cnt = 1; memset(head, -1, sizeof(head));
	rdint(n); rdint(m);
	int S; rdint(S);
	s = 0; t = n + 1;
	for (int i = 1; i <= n; i++) {
		int U; rdint(U);
		addedge(i, t, U, 0); addedge(t, i, 0, 0);
	}
	for (int i = 1; i <= n; i++) {
		int D; rdint(D);
		addedge(s, i, inf, D); addedge(i, s, 0, -D);
	}
	for (int i = 1; i < n; i++) {
		addedge(i, i + 1, S, m); addedge(i + 1, i, 0, -m);
	}
	maxflow_mincost();
	cout << mincost << endl;
    return 0;
}

 

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
好的,你可以参考以下示例代码实现Java销售额查询和营业额统计: ```java import java.util.ArrayList; import java.util.HashMap; import java.util.List; import java.util.Map; public class SalesStatistics { private Map<String, Double> salesData = new HashMap<>(); public SalesStatistics() { // 初始化销售数据 salesData.put("2021-01-01", 1000.0); salesData.put("2021-01-02", 1500.0); salesData.put("2021-01-03", 2000.0); salesData.put("2021-01-04", 1200.0); salesData.put("2021-01-05", 1800.0); } // 查询指定日期的销售额 public double getSalesByDate(String date) { if (salesData.containsKey(date)) { return salesData.get(date); } else { return 0.0; } } // 统计指定日期范围内的营业额 public double getTotalSales(String startDate, String endDate) { double totalSales = 0.0; for (String date : salesData.keySet()) { if (date.compareTo(startDate) >= 0 && date.compareTo(endDate) <= 0) { totalSales += salesData.get(date); } } return totalSales; } // 获取所有销售日期 public List<String> getAllSalesDates() { return new ArrayList<>(salesData.keySet()); } } ``` 使用示例: ```java public static void main(String[] args) { SalesStatistics salesStatistics = new SalesStatistics(); // 查询指定日期的销售额 double sales = salesStatistics.getSalesByDate("2021-01-02"); System.out.println("2021-01-02的销售额为:" + sales); // 统计指定日期范围内的营业额 double totalSales = salesStatistics.getTotalSales("2021-01-02", "2021-01-04"); System.out.println("2021-01-02到2021-01-04的营业额为:" + totalSales); // 获取所有销售日期 List<String> salesDates = salesStatistics.getAllSalesDates(); System.out.println("所有销售日期为:" + salesDates); } ```

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值