众所周知计算机代码底层计算都是0和1的计算,
牛牛知道这点之后就想使用0和1创造一个新世界!
牛牛现在手里有n个0和m个1,给出牛牛可以创造的x种物品,
每种物品都由一个01串表示。
牛牛想知道当前手中的0和1可以最多创造出多少种物品。
输入描述:
输入数据包括x+1行:
第一行包括三个整数x(2 ≤ x ≤ 20),n(0 ≤ n ≤ 500),m(0 ≤ m ≤ 500),以空格分隔
接下来的x行,每行一个01串item[i],表示第i个物品。每个物品的长度length(1 ≤ length ≤ 50)
输出描述:
输出一个整数,表示牛牛最多能创造多少种物品
输入例子:
3 3 1
1
00
100
输出例子:
2
*二维背包问题:
*对于每件物品,当选择这件物品必须同时付出两种代价;
*对于每种代价都有一个可付出的最大值(背包容量)。
*问怎样选择物品可以得到最大的价值。
*设第i件物品所需的两种代价分别为a[i]和b[i]。两种代价可付出的最大值(两种背包容量)分别为u和v。物品的价值为w[i]。
*状态转移方程:dp[i][u][v] = max(dp[i-1][u][v] , w[i] + dp[i-1][u-a[i]][v-b[i]])
*同样的进行空间压缩,我们可以得到二维数组的状态转移方程,如下:
*dp[u][v] = max(dp[u-a[i]][v-b[i]]+w[i],dp[u][v])
*注:u、v在此均采用倒序!
public class Main {
public static void main(String[] args) {
Scanner sc=new Scanner(System.in);
int x=sc.nextInt();
int n=sc.nextInt();
int m=sc.nextInt();
sc.nextLine();
int[] zero = new int[x];
int[] one = new int[x];
for(int i = 0; i < x; i++){
char[] temp = sc.nextLine().toCharArray();
int cnt = 0;
for(int j = 0; j < temp.length; j++){
if(temp[j] == '0')
cnt++;
}
zero[i] = cnt;
one[i] = temp.length - cnt;
}
sc.close();
//物品有0和1两种代价,所以是二维背包
int dp[][] = new int[n+1][m+1];
//dp[i][j]表示有i个0,j个1时,能造出多少物品
for(int i = 0; i < x; i++){
//倒序遍历是因为每一次采用的状态是上一次的,若是正序就会把要用的状态覆盖成本次的
for(int j = n; j >= zero[i]; j--){
for(int k = m; k >= one[i]; k--){
dp[j][k]=Math.max(dp[j][k],dp[j-zero[i]][k-one[i]]+1);
}
}
}
System.out.println(dp[n][m]);
}
}