NEUQ-ACM Week5

P1048 [NOIP2005 普及组] 采药

思路:

1.每株药采一次,在一定时间内所采价值最大为 01背包问题

2.以dp[j]表示当在总共时间为j时可采的最大价值

3.每一种药依次遍历,内部时间从大到小遍历(防止一种药重复计算),得出最大值

代码:

#include<bits/stdc++.h>
using namespace std;
int t,m,a[105],b[105],dp[1005];

int main(){
	cin>>t>>m;
	for(int i=0;i<m;i++){
		cin>>a[i]>>b[i];
	}
	for(int i=0;i<m;i++){
		for(int j=t;j>=a[i];j--){
			dp[j]=max(dp[j],dp[j-a[i]]+b[i]);
		}
	}
	cout<<dp[t];
}

P1616 疯狂的采药

思路:

1.每株药无限采摘,为完全背包问题

2.大体思路与上题一致,内部时间循环转变为从小到大,使得每种药可重复计算

代码:

#include<bits/stdc++.h>
using namespace std;
long long int t,m,a[10000005],b[10005],dp[10000005];

int main(){
	cin>>t>>m;
	for(int i=0;i<m;i++){
		cin>>a[i]>>b[i];
	}
	for(int i=0;i<m;i++){
		for(long long int j=a[i];j<=t;j++){
			dp[j]=max(dp[j],dp[j-a[i]]+b[i]);
		}
	}
	cout<<dp[t];
}

P1049 [NOIP2001 普及组] 装箱问题

思路:

1.题目可以转化为在n个物品中取(每个一次)可填满的最大体积为多少,即01背包问题

2.思路大体与第一题一致,不过限制与需求一致都为体积

3.最后输出再用箱子的体积减去最大体积即剩下的最小体积

代码:

#include<bits/stdc++.h>
using namespace std;
int v,n,a[35],dp[20005];
int main(){
	cin>>v>>n;
	for(int i=0;i<n;i++){
		cin>>a[i];
	}
	for(int i=0;i<n;i++){
		for(int j=v;j>=a[i];j--){
			dp[j]=max(dp[j],dp[j-a[i]]+a[i]);
		}
	}
	cout<<v-dp[v];
}

P1833 樱花

思路:

1.本题将01背包多重背包和完全背包的情况混在了一起

2.可以通过判断可使用个数分类处理

3.完全背包(p=0)直接遍历解;01背包和多重背包可以合在一起解(可用二进制优化)

代码:

#include<bits/stdc++.h>
using namespace std;
int n,h1,h2,m1,m2,T,cnt,k,a,b;
int c[10005],p[10005],t[10005],dp[10005];
int c1[10005],t1[10005];
int main(){
	scanf("%d:%d %d:%d",&h1,&m1,&h2,&m2);
	cin>>n;
	if(m2<m1){
		m2=m2+60;
		h2--;
	}
	T=(h2-h1)*60+m2-m1;
	for(int i=0;i<n;i++)
		scanf("%d%d%d",&t[i],&c[i],&p[i]);
	
	for(int i=0;i<n;i++){
		if(p[i]==0){
			for(int j=t[i];j<=T;j++){
				dp[j]=max(dp[j],dp[j-t[i]]+c[i]);
			}
		}
		else{
		    cnt=1;
		    k=1;
		    a=c[i];
		    b=t[i];
		    while(p[i]>=k){
		    	t1[cnt]=b*k;
		    	c1[cnt++]=a*k;
		    	p[i]-=k;
		    	k*=2;
			}
			t1[cnt]=b*p[i];
		    c1[cnt++]=a*p[i];
		    for(int k=1;k<cnt;k++){
		    	for(int j=T;j>=t1[k];j--){
		    		dp[j]=max(dp[j],dp[j-t1[k]]+c1[k]);
				}
			}//二进制优化
			/*for(int k=1;k<=p[i];k++){
				for(int j=T;j>=t[i];j--){
					dp[j]=max(dp[j],dp[j-t[i]]+c[i]);
				}
			}直接解多重背包*/
		}
	   }
	cout<<dp[T];
}

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值