🍑 机器分配
题目描述
总公司拥有高效设备 M M M 台,准备分给下属的 N N N 个分公司。各分公司若获得这些设备,可以为国家提供一定的盈利。问:如何分配这 M M M 台设备才能使国家得到的盈利最大?求出最大盈利值。其中 M ≤ 15 M \le 15 M≤15, N ≤ 10 N \le 10 N≤10。分配原则:每个公司有权获得任意数目的设备,但总台数不超过设备数 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]);
}
}