输入数据包括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
#include<iostream>
#include<algorithm>
#include<vector>
#include<string>
#include<cmath>
using namespace std;
int main()
{
int x, n, m;
cin >> x >> n >> m;
vector<vector<int>> nmNeed(x, vector<int>(2,0));
for (int i = 0; i < x; i++)
{
string str;
cin >> str;
for (int j = 0; j < str.length(); j++)
{
nmNeed[i][str[j] - '0']++;
}
}
vector<vector<int>> dp(n+1, vector<int>(m+1, 0));
for (int i = 0; i < x; i++)
{
for(int j=n;j>= nmNeed[i][0];j--)
for (int k = m; k >= nmNeed[i][1]; k--)
{
dp[j][k] = max(dp[j][k], dp[j - nmNeed[i][0]][k - nmNeed[i][1]] + 1);
}
}
cout << dp[n][m];
} #include <iostream>
#include <cstring>
#include <algorithm>
using namespace std;
int main(int argc, const char * argv[]) {
int x, U, V;
scanf("%d %d %d", &x, &U, &V);
int f[U + 1][V + 1];
int v0[x], v1[x];
memset(v0, 0, sizeof(v0));
memset(v1, 0, sizeof(v1));
memset(f, 0, sizeof(f));
char s[51];
for (int i = 0; i < x; i++){
cin >> s;
for (int j = 0; j < strlen(s); j++){
if (s[j] == '0'){
v0[i]++;
} else {
v1[i]++;
}
}
}
for (int k = 0; k < x; k++) {
for (int u = U; u >= v0[k]; u--) {
for (int v = V; v >= v1[k]; v--) {
f[u][v] = max(f[u][v], f[u - v0[k]][v - v1[k]] + 1);
}
}
}
cout << f[U][V];
return 0;
}
//经典的二维背包问题
#include <iostream>
#include <vector>
#include <string>
#include <algorithm>
using namespace std;
int main()
{
int x, n, m;
cin >> x >> n >> m;
vector<string> svec(x);
for (int i = 0; i < x; ++i)
cin >> svec[i];
vector<vector<int>> dp(n + 1, vector<int>(m + 1, 0));
int one = 0;
int zero = 0;
for (int i = 0; i < x; ++i)
{
one = zero = 0;
for (int j = 0; j < svec[i].size(); ++j)
{
if (svec[i][j] == '0')
++zero;
else
++one;
}
for (int j = n; j >= zero; --j)
{
for (int k = m; k >= one; --k)
{
dp[j][k] = max(dp[j - zero][k - one] + 1, dp[j][k]);
}
}
}
cout << dp[n][m] << endl;
}
回溯法的会还是比较好理解,动态规划没有做。
package 全国模拟卷2;
import java.util.Scanner;
public class Main_7 {
static int ans=0;
public static void main(String[] args) {
Scanner sc=new Scanner(System.in);
while(sc.hasNext())
{
int x=sc.nextInt();
int n=sc.nextInt();
int m=sc.nextInt();
String []strArr=new String[x];
for(int i=0;i<x;i++)
{
strArr[i]=sc.next();
}
creat(strArr, n, m,x);
}
sc.close();
}
public static void creat(String []strArr,int n,int m,int x)
{
int bits[]=new int [x];
for(int i=0;i<x;i++)
bits[i]=-1;
System.out.println(creat_word(strArr, n, m, x,bits));
}
public static int creat_word(String []strArr,int n,int m,int x,int []bits)
{ int num=0;
if(x==0)
{
return 0;
}
if(n<0||m<0)
return 0;
int bit_1=0;
int bit_0=0;
if(bits[x-1]>=0)
{
bit_0=bits[x-1];
bit_1=strArr[x-1].length()-bit_0;
}
else {
bit_0=getbits(strArr[x-1], '0');
bits[x-1]=bit_0;
bit_1=strArr[x-1].length()-bit_0;
}
if(n-bit_0>=0&&m-bit_1>=0)
num=creat_word(strArr, n-bit_0, m-bit_1, x-1,bits)+1;
num=Math.max(num, creat_word(strArr, n, m, x-1,bits));
return num;
}
public static int getbits(String str,char ch)
{
int num=0;
for(int i=0;i<str.length();i++)
if(str.charAt(i)==ch)
num++;
return num;
}
}
#include<bits/stdc++.h> using namespace std; char s[50+5]; int a[20+5],b[20+5]; int main(){ int x,n,m;scanf("%d%d%d",&x,&n,&m); for(int i=0;i<x;i++){ a[i]=b[i]=0; scanf("%s",s); for(char* p=s;*p!=NULL;p++){ if(*p=='0')a[i]++; else b[i]++; } } int maxc=0; for(int i=1;i<=(1<<x)-1;i++){ int sa=0,sb=0,cnt=0; for(int j=0;j<x;j++){ if(i&(1<<j))sa+=a[j],sb+=b[j],cnt++; } if(sa<=n&&sb<=m)maxc=max(maxc,cnt); } printf("%d\n",maxc); }
import java.util.Scanner;
/**
* 三维背包
* Created by Scruel on 2017/3/29.
* Personal blog : http://blog.csdn.net/scruelt
* Github : https://github.com/scruel
*/
public class CreateNewWorld {
static int x;
static int n;//0
static int m;//1
static int[] item0;
static int[] item1;
static int solve() {
int[][][] dp = new int[x + 1][m + 1][n + 1];
for (int i = 0; i < x; i++) {
for (int j = 0; j <= m; j++) {
for (int k = 0; k <= n; k++) {
//ok
if (item1[i] <= j && item0[i] <= k)
dp[i + 1][j][k] = Math.max(dp[i][j][k], dp[i][j - item1[i]][k - item0[i]] + 1);
else
dp[i + 1][j][k] = dp[i][j][k];
}
}
}
return dp[x][m][n];
}
public static void main(String[] args) {
Scanner input = new Scanner(System.in);
x = input.nextInt();
n = input.nextInt();
m = input.nextInt();
item0 = new int[x];
item1 = new int[x];
input.nextLine();
for (int i = 0; i < x; i++) {
String s = input.nextLine();
for (int j = 0; j < s.length(); j++) {
if (s.charAt(j) == '0')
item0[i]++;
else
item1[i]++;
}
}
System.out.println(solve());
}
}
//也不晓得跟我一样,在做这道题目之前完全没有接触过0-1背包问题的人有多少。
//为了理解这一道题,不得不说煞费苦心的百科查了不少的文章,算是明白了0-1背包问题的一点点皮毛了吧。
//接下来是我自己搜集的有关入门的一些小结。ps:当然基本上是别人总结过的,我只是把自己理解过了的搬运了过来而已
/*
* 基本的0-1背包问题:
* 已知有N类物品,每类物品都只有一件,对应的重量为w[i],价值为v[i]。
* 背包最多承重为W,在不超出承重范围的前提下,求能拿的物件的最大价值为多少
*
*这是DP的一个经典实例,可以用动态规划求解
*设dp(i,j)表示对于前i件物品,背包剩余容量为j时,能取得的最大价值
*状态转移方程:dp(i,j) = Max(dp(i-1,j), dp(i-1,j-w[i])+v[i])
*注: dp(i-1,j) -----》 dp(i,j),即不拿第i件物品
* dp(i-1,j-w[i]) -----》 dp(i,j),即拿第i件物品
* 当物品数量很多,背包的容量很大时,这时要用二维数组往往是不现实的
* 我们可以进行空间压缩,使用一维数组实现
* 状态转移方程:
* dp(j)=Max(dp(j),dp(j-w[i])+v[i])
* 注:对于背包的容量要采用倒序的方式!
*/
/*
* 二维背包问题:
* 对于每件物品,当选择这件物品必须同时付出两种代价;
* 对于每种代价都有一个可付出的最大值(背包容量)。
* 问怎样选择物品可以得到最大的价值。
* 设第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在此均采用倒序!
*
* 例题说明:
* 众所周知计算机代码底层计算都是0和1的计算,牛牛知道这点之后就想使用0和1创造一个新世界!
* 牛牛现在手里有n个0和m个1,给出牛牛可以创造的x种物品,每种物品都由一个01串表示。
* 牛牛想知道当前手中的0和1可以最多创造出多少种物品。
* 等价对应:
* n --------- 背包容量,u
* m --------- 背包容量,v
* x --------- 物品个数
* item[i].0的个数 --------- 物品i对应u部分的容量
* item[i].1的个数 --------- 物品i对应v部分的容量
* 最多创造的物品种数 --------- 可得到的最大价值(此时物品的价值w[i]=1)
*/
//另外常见的还有完全背包问题以及多重背包问题,就不啰嗦了,花点时间,至少在理解上,问题应该不是很大
//感觉难的还是怎么把一个题目抽象到对应背包问题的模型上来,以及相关代码实现的优化。
import java.util.*;
public class dim_2_bag {
public static void main(String[] args) {
Scanner sc = new Scanner(System.in);
while(sc.hasNext()) {
int x = sc.nextInt();
int n = sc.nextInt();
int m = sc.nextInt();
int[] zero = new int[x];
int[] one = new int[x];
String item;
for(int i=0;i<x;i++) {
item = sc.next();
int cnt = 0;
for(int j=0;j<item.length();j++) {
if(item.charAt(j) == '0') {
cnt++;
}
}
zero[i] = cnt;
one[i] = item.length()-cnt;
}
int[][] dp = new int[n+1][m+1];
for(int i=0;i<x;i++) {
for(int j=n;j>=zero[i];j--) {
for(int k=m;k>=one[i];k--) {
if(dp[j][k] < dp[j-zero[i]][k-one[i]]+1) {
dp[j][k] = dp[j-zero[i]][k-one[i]]+1;
}
}
}
}
System.out.println(dp[n][m]);
}
}
}
#include<iostream>
#include<algorithm>
#include<cstring>
using namespace std;
int main(){
char s[51];
int X, N, M, n[21] = { 0 }, m[21] = { 0 }, dp[501][501] = { 0 };
cin >> X >> N >> M;
for (int i = 1; i <= X; i++){
cin >> s;
for (int j = 0; j < strlen(s); j++){
if (s[j] == '0')
n[i]++;
else
m[i]++;
}
}
for (int i = 1; i <= X; i++)
for (int j = N; j >= n[i]; j--)
for (int k = M; k >= m[i]; k--)
dp[j][k] = max(dp[j][k], dp[j - n[i]][k - m[i]] + 1);
//二维背包,使用动态规划求dp数组
cout << dp[N][M];
return 0;
}
def creatNewWorld():
firstline = input()
x, n, m = [int(n) for n in firstline.split()]
zeros = [ 0 for i in range(x)]
ones = [ 0 for i in range(x)]
for i in range(x):
item = str(input())
zeros[i], ones[i] = count0and1(item)
val = [[0 for i in range(m + 1)] for j in range(n + 1)]
for k in range(1,x+1):
for i in range(n, zeros[k-1] - 1, -1):
for j in range(m, ones[k-1] - 1, -1):
val[i][j] = max(val[i][j], 1 + val[ i-zeros[k-1] ][ j-ones[k-1] ])
print(val[n][m])
def count0and1(item):
c1 = 0
for n in item:
if int(n) == 1:
c1 += 1
return len(item) - c1, c1
creatNewWorld() 总是提示 运行超时:
您的程序未能在规定时间内运行结束,请检查是否循环有错或算
法复杂度过大。 case通过率为70.00%。
明明复杂度和其他人的一样啊
# -*- coding: cp936 -*-
x = raw_input().split()
x1 = int(x[0])
x2 = int(x[1])
x3 = int(x[2])
w0 = []
w1 = []
for i in range(x1):
l.append(raw_input())
for i in range(len(l)):
w0.append(l[i].count('0'))
w1.append(len(l[i])-w0[i])
bag0 = range(0,x2+1)
bag1 = range(0,x3+1)
f = [[0 for i in range(x3+1)] for j in range(x2+1)] l =[]
for i in range(x1-1,-1,-1): for j in range(x2,-1,-1):#2 1 0 for k in range(x3,-1,-1):#0 if bag1[k] < w1[i] or bag0[j] < w0[i]: break else: f[j][k] = max(f[j][k],1 + f[bag0[j]-w0[i]][bag1[k]-w1[i]])
print f[x2][x3]
背包问题的变形。。。刚开始真的是读不懂题。。。
#include<iostream>
#include<vector>
#include<cstring>
using namespace std;
int main()
{
int x,n,m;
cin>>x>>n>>m;
vector<string>v(x);
for(int i=0;i<x;i++)
cin>>v[i];
int z[x];
memset(z,0,sizeof(z));
int o[x];
memset(o,0,sizeof(o));
for(int i=0;i<x;i++)
for(int j=0;j<v[i].length();j++)
if(v[i][j]=='0')
z[i]++;
else
o[i]++;
int dp[n+1][m+1];
memset(dp,0,sizeof(dp));
for(int i=0;i<x;i++)
for(int j=n;j>=z[i];j--)
for(int k=m;k>=o[i];k--)
dp[j][k]=max(dp[j][k],dp[j-z[i]][k-o[i]]+1);
cout<<dp[n][m]<<endl;
return 0;
}
#include <iostream>
#include <stdlib.h>
#include <string>
#include <vector>
#include <algorithm>
using namespace std;
int countChar(string str, char c)
{
int n=0;
for (int i=0 ;i<str.length() ; ++i)
{
if (str[i] == c)
{
n++;
}
}
return n;
}
int main()
{
int n,m,strNum;
string strTmp;
vector<string> obj;
vector<int> n0,n1;
cin>>strNum>>n>>m;
for (int i=0; i<strNum;++i)
{
cin>>strTmp;
obj.push_back(strTmp);
n0.push_back(countChar(strTmp,'0'));
n1.push_back(countChar(strTmp,'1'));
}
int max = 0;
vector<int> num(strNum,1);
for (int i=1; i<strNum; ++i)
{
int t0 = n0[i];
int t1 = n1[i];
for (int j=0; j<i; ++j)
{
t0 += n0[j];
t1 += n1[j];
if (t0 <= n && t1 <= m && num[j]+1 > num[i])
{
num[i] = num[j] + 1;
if (max < num[i])
{
max = num[i];
}
}
else
{
t0 -= n0[j];
t1 -= n1[j];
}
}
}
cout<<max<<endl;
return 0;
}