算法分析
此题是分组背包求具体方案问题
-
1、由于题目答案不唯一,输入任意合法方案即可
-
2、通过多重背包模版求出最大盈利值
f[n][m]
-
3、求具体方案,由于每个公司可以分配不同数量的机器,因此从
n
遍历到1
,假设k
为当前公司分配的机器数量,则若满足f[i][j] == f[i - 1][j - k] + w[i][k]
,其中f[i][j]
为当前最优情况,则表示f[i][j]
可以从f[i - 1][j - k]
状态转移过来,输出当前k
值
时间复杂度 $O(nm^2)$
参考文献
算法提高课
Java 代码
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
public class Main {
static int N = 11;
static int M = 16;
static int[][] w = new int[N][M];
static int[][] f = new int[N][M];
static int n;
static int m;
public static void main(String[] args) throws IOException{
BufferedReader reader = new BufferedReader(new InputStreamReader(System.in));
String[] s1 = reader.readLine().split(" ");
n = Integer.parseInt(s1[0]);
m = Integer.parseInt(s1[1]);
for(int i = 1; i <= n;i++)
{
String[] s2 = reader.readLine().split(" ");
for(int j = 1;j <= m;j++)
{
w[i][j] = Integer.parseInt(s2[j - 1]);
}
}
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]);
}
}
}
System.out.println(f[n][m]);
int j = m;
for(int i = n;i >= 1;i--)
{ //选择k个机器
for(int k = 0;k <= j;k ++)
{
if(f[i][j] == f[i - 1][j - k] + w[i][k])
{
System.out.println(i + " " + k);
j -= k;
break;
}
}
}
}
}
大佬,这道题到底是多重,还是分组啊?明明是多重就可以AC掉,为什么要说是分组背包呢?
还有,这个代码在别的网站上交上去直接编译错误了
http://ybt.ssoier.cn:8088/problem_show.php?pid=1266
这一段有问题吧,i是倒过来做的啊,不应该拿个数组保存一下然后循环外输出吗
逆着循环,为什么输出的结果是错误的呢?
但是如果改成下面的代码就是正确的,这是为什么啊,求大佬解答
您这时间复杂度咋算的啊,不是 $O\left(nm^2\right)$ 吗?
已修改hh
大哥这个为什么不能像“背包问题求具体方案”一样从后往前找最大值,而是从前往后
都可以的,这题没有特别的要求,背包问题求具体方案 要求字典序最小,如果这题按照 背包问题求具体方案 去做也是可以的
好的大哥我试试
如果这里要求每一组用了多少台机器,按照组数的大小编号从小到大输出,那可以像y总一样,从
f[n][m]
出发,查找到每一组用了什么,记录到way[]
数组中,way[i]
表示的是每一组选了多少台机器,再从小到大输出大哥这Dp题目做着做着就容易昏,太难想了,你是怎么想出来这些过程的
看过y总怎么解,然后深入理解,再复习下hh
只能膜拜了
摩拜大神