303 条题解
-
7
larryzhong LV 9 @ 7 年前
-
27 个月前@
-
27 年前@
#include<iostream>
#include<cstdio>
using namespace std;
int w[1005];
int k[1005];
int f[1005]; //一维优化
int main()
{
int n,s;
scanf("%d",&s);
scanf("%d",&n);
for(int i=1;i<=n;i++)
{
scanf("%d%d",&w[i],&k[i]);
}
for(int i=1;i<=n;i++)
{
for(int j=s;j>=w[i];j--)
{
f[j]=max(f[j-w[i]]+k[i],f[j]);
}
}
printf("%d",f[s]);
return 0;
} -
27 年前@
#include<algorithm>
#include<iostream>
#include<cstring>
#include<cstdio>
#include<cmath>
using namespace std;
long long t[110],m[110],f[1010][1010];
int main()
{
int a,n;//a表示总时间,n表示山洞里草药的数目
cin>>a>>n;
for(int i=1;i<=n;i++)
cin>>t[i]>>m[i];//循环输入每种草药采摘所需的时间和价值
for(int i=1;i<=n;i++)
for(int j=0;j<=a;j++)
{
if(j>=t[i])//如果总时间大于采药所需时间
f[i][j]=max(f[i-1][j],f[i-1][j-t[i]]+m[i]);
else f[i][j]=f[i-1][j];
//对比不采当前草药能获得的最大价值和采当前草药能获得的最大价值
}
cout<<f[n][a]<<endl;//输出最大价值
return 0;
} -
27 年前@
c++ 啦啦啦啦啦啦
#include<algorithm>
#include<iostream>
#include<cstring>
#include<cstdio>
#include<cmath>
using namespace std;
long long t[110],m[110],f[1010][1010];
int main()
{
int a,n;//a表示总时间,n表示山洞里草药的数目
cin>>a>>n;
for(int i=1;i<=n;i++)
cin>>t[i]>>m[i];//循环输入每种草药采摘所需的时间和价值
for(int i=1;i<=n;i++)
for(int j=0;j<=a;j++)
{
if(j>=t[i])//如果总时间大于采药所需时间
f[i][j]=max(f[i-1][j],f[i-1][j-t[i]]+m[i]);
else f[i][j]=f[i-1][j];
}
cout<<f[n][a]<<endl;
return 0;
} -
27 年前@
啦啦啦啦啦啦
#include<algorithm>
#include<iostream>
#include<cstring>
#include<cstdio>
#include<cmath>
using namespace std;
long long c[1010],w[1010],f[1010][1010];
int main()
{
int V,n;
cin>>V>>n;
for(int i=1;i<=n;i++)
cin>>c[i]>>w[i];
for(int i=1;i<=n;i++)
for(int j=0;j<=V;j++)
{
if(j>=c[i])
f[i][j]=max(f[i-1][j],f[i-1][j-c[i]]+w[i]);
else f[i][j]=f[i-1][j];
}
cout<<f[n][V]<<endl;
return 0;
} -
110 个月前@
这道题目主要靠01背包
可以使用最经典的核心代码:代码如下:
-
13 年前@
-
14 年前@
本题是0/1背包
我关于0/1背包的讲解:【精讲】DP经典问题——0/1背包问题 -
14 年前@
简单的01背包问题
-
14 年前@
介是一道标准的01背包辣~
01背包是O(NW)的复杂度
所以是双循环枚举呀
第一层1~n枚举物品
第二层W~w[i]枚举背包容量
tips:w[i]指的是第i个物品的体积呀
第二步要推柿子
没对于每个空间,最大价值有两种决策
放:f[j]
不放:f[j-w[i]]+c[i]
求个最大就好啦
上代码啦:
#include<bits/stdc++.h>
using namespace std;
int W,n;
int w[110],c[110],f[1100];
int main()
{
cin>>W>>n;
for(int i=1;i<=n;i++)scanf("%d%d",&w[i],&c[i]);
for(int i=1;i<=n;i++)
for(int j=W;j>=w[i];j--)f[j]=max(f[j],f[j-w[i]]+c[i]);
cout<<f[W];
}
好简单呢~ -
15 年前@
背包模板。 我第一次发题解,大家多多照顾 。
很显然本题的数据范围是,完全可以用一些剪枝写过去。
但是,如果,那么就只能.
用表示用的容量选择前个物品可以获得的最大价值。
那么,我们需要考虑第个物品。
dp[i][j]=max(dp[i-1][j],dp[i-1][j-v[i]]+w[i]);
前者:不选当前的。
后者:选当前的,背包容量缩小,加上当前的价值。
然而数组下标显然非负,所以要保证,否则就只能选择dp[i-1][j]
二维数组的好处是:**不用考虑循环的正反问题。**
显然可以弄成一维(滚动数组),但是没必要,那样还要研究循环的正反,太麻烦。(当然除非真的有内存的压缩需求)
献上本巨佬的代码。
-
15 年前@
f是动态规划数组。
x为时间,y为价值。
二维时由上一层推来,状态转移方程:
f[i,j]:=max(f[i,j],f[i-1,j-x]+y);
而现在改成了一维,状态要倒着放,
否则当前一层前面的状态会影响目前的操作。
状态转移方程:
f[i]:=f[i-x]+y;
这绝对是最简单的动规写法......
Pascal程序:
var n,m,i,j,x,y,max:longint;
f:array[0..1001] of longint;
begin
readln(m,n);
for i:=1 to n do
begin
readln(x,y);
for j:=m downto x do
if f[j-x]+y>f[j] then
f[j]:=f[j-x]+y;
end;
for i:=1 to m do
if f[i]>max then
max:=f[i];
writeln(max);
end. -
16 年前@
现在这么流行DP吗?
我特别喜欢写DFS,不过是个编程的人都知道暴力是不可以过的。
所以我加了最优性剪枝(启发式搜索)
详见代码 -
16 年前@
-
16 年前@
#include<iostream>
using namespace std;
typedef long long ll;
const int maxx=6666;
int main()
{
ll f[maxx],w[maxx],v[maxx],n,t;
cin>>t>>n;
for(int i=1;i<=n;i++)
cin>>w[i]>>v[i];
for(int i=1;i<=n;i++)
for(int j=t;j>=w[i];j--)
{
f[j]=max(f[j],f[j-w[i]]+v[i]);
}
cout<<f[t];
return 0;
} -
16 年前@
水题,pascal代码见下
-
17 年前@
-
17 年前@
典型的01背包问题,用一维数组解决,不需要存数据
import java.util.Scanner;
public class Main {
static Scanner in = new Scanner(System.in);
static int n, m;
static int[] dp = new int[105];
public static void main(String[] args) {
n = in.nextInt();
m = in.nextInt();
for (int i = 1; i <= m; i++) {
int a = in.nextInt();
int b= in.nextInt();
for (int j = n; j >= 0; j--) {
if (j >= a) {
dp[j] = Math.max(dp[j], dp[j - a] + b);
}
}
}
System.out.println(dp[n]);
}}
-
17 年前@