5.29身败名裂

busses

本题第一眼可能会让人迷惑,拨开题面看本质,这里里程其实可以看作十种物品同时里程也是所占体积,耗油数就是价值,随意换乘意味着物品可以取随意多件,那么这就是一个完全背包,总体积为想要行驶的里程数
代码:

#include<bits/stdc++.h>
#define N 1000005
#define ll long long
using namespace std;
inline int read(){
    
    
	int x=0,f=1;char c=getchar();
	while(!isdigit(c)){
    
    if(c=='-')f=-1;c=getchar();}
	while(isdigit(c)){
    
    x=x*10+c-'0';c=getchar();}
	return x*f;
}
int a[20],dp[500],d[11]={
    
    0,1,2,3,4,5,6,7,8,9,10};
int main(){
    
    
	for(int i=1;i<=499;i++)dp[i]=1e9;
	for(int i=1;i<=10;i++)a[i]=read();
	int n=read();
	for(int i=1;i<=10;i++)
		for(int j=d[i];j<=n;j++)
			dp[j]=min(dp[j],dp[j-d[i]]+a[i]);
	printf("%d",dp[n]);
	return 0;
}

注意:这里求最小值,要注意dp数组的初始化

prime

本题迷惑性极强,很容易让人去打素数表用数学方法求解,但如果我们将素数作为多个物品,素数的大小作为体积,本题就又变成了一个完全背包
代码:

#include<bits/stdc++.h>
#define N 1000005
#define ll long long
using namespace std;
inline int read() {
    
    
	int x=0,f=1;
	char c=getchar();
	while(!isdigit(c)) {
    
    
		if(c=='-')f=-1;
		c=getchar();
	}
	while(isdigit(c)) {
    
    
		x=x*10+c-'0';
		c=getchar();
	}
	return x*f;
}
int prime[1005],pcnt,cnt[1005];
ll  dp[1005];
int used[1005];
int isprime[1005];
int main() {
    
    
	for(int i=2; i<=200; i++) {
    
    
		int flag=0;
		for(int j=2; j<i; j++)
			if(!(i%j)) {
    
    
				flag=1;
				break;
			}
		if(!flag) {
    
    
			prime[++pcnt]=i;
			isprime[i]=1;
		}
	}
	dp[0]=1;
	for(int i=1; i<=pcnt; i++)
		for(int j=prime[i]; j<=200; j++)
			dp[j]+=dp[j-prime[i]];
	int n;
	while(scanf("%d",&n)!=EOF)printf("%lld\n",dp[n]);
	return 0;
}

注意:
1、方案数需要求和而不是取最大值
2、多测可以离线计算,一定要注意到多测!

hallows

多重背包板子,要注意背包溢出问题
代码:

#include<bits/stdc++.h>
#define N 10005
#define ll long long
using namespace std;
inline ll read(){
    
    
	int x=0,f=1;char c=getchar();
	while(!isdigit(c)){
    
    if(c=='-')f=-1;c=getchar();}
	while(isdigit(c)){
    
    x=x*10+c-'0';c=getchar();}
	return x*f;
}
ll m[N],w[N],s[N],dp[N];
int main(){
    
    
	ll n=read(),v=read();
	for(int i=1;i<=n;i++){
    
    m[i]=read();w[i]=read();s[i]=read();}
	for(int i=1;i<=n;i++)
		for(int j=v;j>=w[i];j--)
			for(int k=1;k<=m[i]&&j>=k*w[i];k++)
				dp[j]=max(dp[j],dp[j-k*w[i]]+k*s[i]);
	printf("%lld",dp[v]);
	return 0;
}

pgrune

多重+二维背包,可以使用哈希合并维度(不建议使用)
代码:

#include<bits/stdc++.h>
#define N 10005
#define ll long long
using namespace std;
inline ll read(){
    
    
	int x=0,f=1;char c=getchar();
	while(!isdigit(c)){
    
    if(c=='-')f=-1;c=getchar();}
	while(isdigit(c)){
    
    x=x*10+c-'0';c=getchar();}
	return x*f;
}
ll p[N],r[N],dp[N][N],v[N],m[N];
int main(){
    
    
	ll n=read(),P=read(),R=read();
	for(int i=1;i<=n;i++){
    
    p[i]=read(),r[i]=read(),m[i]=read(),v[i]=read();if(!m[i])m[i]=1e9;}
	for(int i=1;i<=n;i++)
		for(int x=P;x>=p[i];x--)
			for(int y=R;y>=r[i];y--)
				for(int k=1;k<=m[i]&&x>=k*p[i]&&y>=k*r[i];k++)
					dp[x][y]=max(dp[x][y],dp[x-k*p[i]][y-k*r[i]]+k*v[i]);
	printf("%lld",dp[P][R]);
	return 0;
}

猜你喜欢

转载自blog.csdn.net/MuLaSaMe/article/details/117388577
今日推荐