0
点赞
收藏
分享

微信扫一扫

Makefile 简易教程

追梦人的自留地 2023-05-15 阅读 108

🍑 机器分配

题目描述

总公司拥有高效设备 M M M 台,准备分给下属的 N N N 个分公司。各分公司若获得这些设备,可以为国家提供一定的盈利。问:如何分配这 M M M 台设备才能使国家得到的盈利最大?求出最大盈利值。其中 M ≤ 15 M \le 15 M15 N ≤ 10 N \le 10 N10。分配原则:每个公司有权获得任意数目的设备,但总台数不超过设备数 M M M

输入格式

第一行有两个数,第一个数是分公司数 N N N,第二个数是设备台数 M M M

接下来是一个 N × M N \times M N×M 的矩阵,表明了第 i i i 个公司分配 j j j 台机器的盈利。

输出格式

第一行为最大盈利值。

接下来 N N N 行为第 i i i 分公司分 x x x 台。

P.S. 要求答案的字典序最小。

样例 #1

样例输入 #1

3 3
30 40 50
20 30 50
20 25 30

样例输出 #1

70
1 1
2 1
3 1

🍑 DFS出奇迹

import java.util.Scanner;

public class Main
{
	static int n, m, N = 20;
	static int[][] w = new int[N][N];
	static int[][] f = new int[N][N];
	static int ans;
	static int[] res = new int[N];// 存最终的结构
	static int[] tmp = new int[N];// 临时数组暂存结果

	public static void main(String[] args)
	{
		Scanner sc = new Scanner(System.in);
		n = sc.nextInt();
		m = sc.nextInt();
		for (int i = 1; i <= n; i++)
			for (int j = 1; j <= m; j++)
				w[i][j] = sc.nextInt();

		dfs(0, 0, m);
		System.out.println(ans);
		for (int i = 1; i <= n; i++)
			System.out.println(i + " " + res[i]);
	}

//	num是当前公司,v是当前盈利,cnt是剩余的机器数量
	private static void dfs(int u, int v, int cnt)
	{
		if (cnt < 0)// 非法越界
			return;
		if (u == n + 1)
		{
			if (v > ans)
			{
				ans = v;
				for (int i = 1; i <= n; i++)
					res[i] = tmp[i];
			}
			return;
		}

		for (int i = 0; i <= m; i++)// i 枚举当前公司分配多少台机器
		{
			tmp[u] = i;
			dfs(u + 1, v + w[u][i], cnt - i);
		}
	}
}

🍑 递推版(非字典序)

import java.util.Scanner;

public class Main
{
	static int N = 20;
	static int[][] w = new int[N][N];// 表示 第 i 家公司分配 j 台机器的盈利
	static int[][] f = new int[N][N];

	public static void main(String[] args)
	{
		Scanner sc = new Scanner(System.in);
		int n = sc.nextInt();
		int m = sc.nextInt();
		for (int i = 1; i <= n; i++)
			for (int j = 1; j <= m; j++)
				w[i][j] = sc.nextInt();

		for (int i = 1; i <= n; i++)// 枚举公司
			for (int j = 0; j <= m; j++)// 枚举总体积
				for (int k = 0; k <= j; k++)// 枚举分配台数
					f[i][j] = Math.max(f[i][j], f[i - 1][j - k] + w[i][k]);

		int[] ans = new int[N];
		int j = m;
		for (int i = n; i > 0; i--)// 最终态是 f[n][m] 路径得从后往前推
			for (int k = 0; k <= j; k++)
				if (f[i][j] == f[i - 1][j - k] + w[i][k])
				{
					ans[i] = k;
					j -= k;
					break;
				}
		System.out.println(f[n][m]);
		for (int i = 1; i <= n; i++)
			System.out.println(i + " " + ans[i]);
	}
}
举报

相关推荐

0 条评论