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;
}