题意:
众所周知计算机代码底层计算都是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在此均采用倒序!
代码:
#include <stdio.h>
#include <string.h>
#define Max 502
int max(int x,int y)
{
return x>y?x:y;
}
int main()
{
int x,m,n,i,j,k;
int dp[Max][Max]={0};
int num_N[22]={0};
int num_M[22]={0};
char item[52];
scanf("%d %d %d",&x,&n,&m);
for(i=1;i<=x;i++)
{
scanf("%s",item);
for(j=0;j<strlen(item);j++)
{
if(item[j]=='0')num_N[i]++;
else if(item[j]=='1')num_M[i]++;
}
}
for(i=1;i<=x;i++)
{
for(j=n;j>=num_N[i];j--)
{
for(k=m;k>=num_M[i];k--)
{
dp[j][k]=max(dp[j-num_N[i]][k-num_M[i]]+1,dp[j][k]);
}
}
}
printf("%d\n",dp[n][m]);
return 0;
}