zoukankan      html  css  js  c++  java
  • B1.K for the Price of One(Easy Version)

    题意:Vasya去商店购买物品,她可以购买k件物品,只需支付其中最昂贵的那一件就可以了,或者直接单件购买。她有p个硬币,给出n件物品的价格,需要保证购买每件物品的时候,剩余的钱要大于这件物品的价格。

    分析:可以采用贪心策略,我们尽量用钱包里的钱去单买便宜的物品,那么就可以买的越多,然后用另一种方式去购买昂贵的物品。我们先排序一下,那么所有物品的价格就会从小到大排序,然后
    枚举单买的前k - 1件物品,从0 ~ k - 1,为什么不枚举到k呢?因为枚举到k了,那么采用第二种方式的价格更优。

    //代码如下

    #include <iostream>
    #include <cstdio>
    #include <cstring>
    #include <vector>
    #include <algorithm>
    
    using namespace std;
    
    using LL = long long;
    
    int main()
    {
    	int t;
    	scanf("%d", &t);
    
    	while (t--)
    	{
    		int n, p, k;
    
    		scanf("%d%d%d", &n, &p, &k);
    
    		vector<int> a(n);
    
    		for (int i = 0; i < n; ++i)
    		{
    			scanf("%d", &a[i]);
    		}
    
    		//排序
    		sort(a.begin(), a.end());
    
    		//答案
    		int ans = 0, now = 0, cnt = 0, pre = 0;
    
    		//pre:前i个物品的总价格
    		//枚举前k - 1个单买,剩下的用第二个技能买
    		for (int i = 0; i < k; ++i)
    		{
    			now = pre;
    			cnt = i;
    			//钱包钱不够
    			if (p < now)
    			{
    				break;
    			}
    			for (int j = i + k - 1; j < n; j += k)
    			{
    				now += a[j];
    				if (now <= p)
    				{
    					cnt += k;
    				}
    				else
    					break;
    			}
    			ans = max(ans, cnt);
    			//累加该物品,作为下次循环使用
    			pre += a[i];
    		}
    		printf("%d
    ", ans);
    	}
    
    
    
    	return 0;
    }
    

    分析2:可以采用DP策略,首先前提是,如果我们买了第i件物品的话,那么第i - 1物品的价格应该小于这件物品,显然这样购买的顺序是最优解,因此我们先排序一下。
    可以看出,这是一道背包问题,我们把f[i]表示为购买前i件物品所需的最小价钱,那么因为存在两种购买方式,f[i]可以由这两种方式转移过来,f[i]可以由f[i - 1] + a[i]转移过来,或者
    可以由f[i - k] + a[i]转移过来,其中有k - 1物品不需要支付价格,那么得到的f[i] <= p,那么它的数量就可以更新ans这个记录答案的变量。

    代码如下:

    #include <iostream>
    #include <cstdio>
    #include <cstring>
    #include <algorithm>
    
    using namespace std;
    
    const int N = 2e5 + 5;
    int a[N];
    int f[N];
    
    int main()
    {
    	int t;
    	scanf("%d", &t);
    
    	int n, p, k;
    
    	while (t--)
    	{
    		scanf("%d%d%d", &n, &p, &k);
    		for (int i = 1; i <= n; ++i)
    			scanf("%d", &a[i]);
    
    		sort(a + 1, a + n + 1);
    
    		int ans = 0;
    		//购买前i件物品所需的最低价格
    		for (int i = 1; i <= n; ++i)
    		{
    			f[i] = f[i - 1] + a[i];
    			if (i >= k)
    			{
    				f[i] = min(f[i], f[i - k] + a[i]);
    			}
    			if (f[i] <= p)
    				ans = max(ans, i);
    		}
    
    		printf("%d
    ", ans);
    	}
    
    
    
    
    	return 0;
    }
    
    
  • 相关阅读:
    深入探讨this指针
    杂谈:你选择coco 还是unity3d?
    一分钟制作U盘版BT3
    【转载】ShowWindow函数
    hadoop备记
    OA系统权限管理设计(转载)
    二叉树的存储与遍历
    这难道是CSDN的BUG? 大家帮忙看看哪里有问题
    Cookie 操作工具类
    Java实现 蓝桥杯VIP 算法训练 数的统计
  • 原文地址:https://www.cnblogs.com/pixel-Teee/p/12098715.html
Copyright © 2011-2022 走看看