浙江大学软件学院2020年保研上机模拟练习 7-4 Shopping With Coupons

Posted CSU迦叶

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了浙江大学软件学院2020年保研上机模拟练习 7-4 Shopping With Coupons相关的知识,希望对你有一定的参考价值。

首先是题目的理解上:有n个商品,n张优惠券,实际上能买的商品个数最多就是n*n,为啥呢,这题默认是买一个商品必须用一张券,而且一个商品每张面值的券只能用一次。也就是,即使有1个6元的商品,当券对这个商品全部用过一次,即使有10元商品和最大面值3的券,也只能够选后者。

第一次我套用了0-1背包的动态规划,但是遗憾的是,由于背包容量(在本题是钱的数量大于10的6次方),即使把真实价格按照从低到高排序,取前1000个,动规本身也会造成超时。

第二次我在计算每件商品实际要付出的价格时,程序是这么写的

int num = 0;
for(int i=0;i<n&&num<1000000;i++){
	for(int j=n-1;j>=0&&num<1000000;j--){
		int t = v[i]-c[j];
		pac[num++]=t;
	}
}

此前,v和c都已经从低到高排序了,也就是只读入最小的前100w个,然后使用贪心,只要钱足够就买入。这次没有超时。但是有一个用例是答案错误。

分析可能有两个原因:1.贪心本身就不科学 2.以我刚刚的计算方法,得到的并不是真正最小的前100w个价格。

我尝试计算出所有可能的价格,进行排序,再取前100w个,很遗憾,2个超时,得分甚至更低。 

我幡然醒悟,这题是追求最大商品个数,又不是价值,本来就不是动规问题,因此把价值从低到高一件件地往购物车里放就是能够得到最多商品数的策略。

问题就出在如何不超时地得到从低到高的价格排序,且我得到的100w是死的,也许它要100w+1呢?

也就是我的26分程序丢分点可能在于:1.不是严格的小到大价格排序 2.给出的价格排序满足时间复杂度但是剩余的钱还能买

怎么办?只能改成动态的。

友情外链:浙江大学软件学院2020年保研上机模拟练习

第一次程序

#include<cstdio>
#include<iostream>
#include<algorithm>
#include<cmath>
#include<string>
#include<cstring>
#include<vector>
#include<queue>

using namespace std;

const int maxn = 100010;
const int inf = 1000000+10;//即10^6

vector<int> pac;//price after coupon
int dp[inf] = {0};

int n,W;
int v[maxn],c[maxn];

int main(){
	
	scanf("%d %d",&n,&W);
	for(int i=0;i<n;i++){
		int t;
		scanf("%d",&t);
		v[i] = t;
	}
	for(int i=0;i<n;i++){
		int t;
		scanf("%d",&t);
		c[i] = t;
	}
	for(int i=0;i<n;i++){
		for(int j=0;j<n;j++){
			int t = v[i]-c[j];
			pac.push_back(t);
		}
	}
	
	sort(pac.begin(),pac.end());

	for(int i=0;i<n*n;i++){
		for(int w = W;w>=pac[i];w--){
			dp[w] = max(dp[w-pac[i]]+1,dp[w]);
		}
	}
	
	int maxDp = -1;
	int maxNum = 0;
	for(int w = 0;w<=W;w++){
		if(dp[w]>maxNum){
			maxNum = dp[w];
			maxDp = w;
		}
	}
	
	printf("%d %d",maxNum,W-maxDp);
	
	return 0; 
}
 

第一次结果

 第二次程序

#include<cstdio>
#include<iostream>
#include<algorithm>
#include<cmath>
#include<string>
#include<cstring>
#include<vector>
#include<queue>

using namespace std;

const int maxn = 100010;
const int inf = 1000000+10;//即10^6

int pac[1000000];//price after coupon
int dp[inf] = {0};

int n,W;
int v[maxn],c[maxn];

int main(){
	
	scanf("%d %d",&n,&W);

	for(int i=0;i<n;i++){
		int t;
		scanf("%d",&t);
		v[i] = t;
	}
	sort(v,v+n);
	for(int i=0;i<n;i++){
		int t;
		scanf("%d",&t);
		c[i] = t;
	}
	sort(c,c+n);
	
	int num = 0;
	for(int i=0;i<n&&num<1000000;i++){
		for(int j=n-1;j>=0&&num<1000000;j--){
			int t = v[i]-c[j];
			pac[num++]=t;
		}
	}
	
	sort(pac,pac+num);
	
	int left = W;
	int iNum = 0;
	
	for(int i=0;i<num;i++){
		if(left>=pac[i]){
			left-= pac[i];
			iNum ++;	
		}
		if(left<=0)break;		
	}
	
	
	
	printf("%d %d",iNum,left);
	
	return 0; 
}
 

以上是关于浙江大学软件学院2020年保研上机模拟练习 7-4 Shopping With Coupons的主要内容,如果未能解决你的问题,请参考以下文章

浙江大学软件学院2020年保研上机模拟练习 7-3 Partial School Ranking

浙大保研2019年上机题 7-4 Index of Popularity (30分)

2021年保研夏令营经验贴

华中科技大学_2006保研___考研计算机_复试上机

北京邮电大学研究生的计算机专业上机复试我要用啥环境练习啊?用C语言编程软件可以么?

保研——夏令营预推免全过程经验贴