• 贪心基础题目整理


    1.钓鱼(简化移动时间)

    算是经典的题目了

    约翰 钓鱼h小时(1≤h≤16,h*12个单位时间,5分钟为一个单位时间),

    有n个池塘(2≤n≤25),分布在一条直线上,依次为L1,L2,…,Ln,从池塘Li到池塘Li+1要花去约翰ti个单位时间。约翰出发点为L1。

    约翰可以任选若干个池塘垂钓,并且在每个池塘他都可以呆上任意个单位时间。

    每个池塘的鱼会越钓越少。池塘Li在第一个单位时间内能钓到的鱼为Fi(0≤Fi≤100),并且每过一个单位时间在单位时间内能钓到的鱼将减少一个常数di(0≤di≤100),现在请你编一个程序计算约翰最多能钓到多少鱼。

    大概解法就是猜测按顺序移动到各个池塘并吊上一段时间的鱼是比较优的

    再者,怎样确定我在当前池塘钓鱼钓多久呢

    这个好办,把所有的当前指定池塘的鱼塞到优先队列里,每次都选最大的那个进行钓鱼,钓一次就减一次,也就是说,这不会干涉鱼塘的状态,回过来看并没有再跑回去钓鱼,只是在总体上用最优策略选择了某个池塘在现有条件下最优,就再钓到下一个程度

    #include <queue>
    #include <cstdio>
    #include <cstdlib>
    #include <cstring>
    #include <iostream>
    #include <algorithm>
    using namespace std;
    inline int read()
        {
        int x = 0, c = getchar();
        while(c < '0' || c > '9') c = getchar();
        while(c >= '0' && c <= '9') x = x * 10 + c- '0', c = getchar();
        return x;
        }
    struct pool {
        int fish, id;
        bool operator < (pool other) const {
            return fish < other.fish;
        }
    }a[30];
    priority_queue<pool>q;
    int n, h, d[30], t[30], ans;
    int main()
        {
        n = read(), h = read() * 12;
        for(int i = 1; i <= n; ++i) a[i].fish = read(), a[i].id = i;
        for(int i = 1; i <= n; ++i) d[i] = read();
        for(int i = 1; i < n; ++i) t[i] = read();
        for(int i = 1; i <= n; ++i)
            {
            h -= t[i - 1];
            while(!q.empty()) q.pop();
            for(int j = 1; j <= i; ++j) q.push(a[j]);
            int now = 0;
            for(int j = 1; j <= h; ++j)
                {
                pool s = q.top();
                if(s.fish > 0)
                    now += s.fish, s.fish -= d[s.id];
                q.pop();
                q.push(s);
                }
            ans = max(ans, now);
            }
        printf("%d
    ", ans);
        return 0;
        }
    

     2.可扩充背包

    用n个物体塞一个背包,每放进去一个物品,背包的体积就会变大

    解:对于a<b,当然把a从小到大排序后塞就行,证明:因为a<b,所以对这些东西不管按什么顺序塞进去,当前背包的容量一定是随塞入物体单增的,那么先塞小的物体留下的相对空间就越大,因而成立;对于剩下的物块,a > b,因为物体塞完后剩余空间是一定的,所以可以倒过来看成是从背包里取物体,那么策略就和a < b时的方式相同。所以先塞类型1物体再塞类型2物体就行了。

    #include <vector>
    #include <stdio.h>
    #include <string.h>
    #include <iostream>
    #include <algorithm>
    using namespace std;
    inline void read(int &x)
    	{
    	x = 0; int c = getchar();
    	while(c < '0' || c > '9') c = getchar();
    	while(c >= '0' && c <= '9') x = x * 10 + c - 48, c = getchar();
    	}
    int n, T, v;
    long long h;
    struct thg { int a, b;};
    vector<thg> A,B;
    bool cp1(const thg &x, const thg &y) {return x.a < y.a;}
    bool cp2(const thg &x, const thg &y) {return x.b > y.b;}
    bool Jud()
    	{
    	for(int i = 0; i < A.size(); ++i)
    		{
    		if(h < A[i].a) return false;
    		h += A[i].b - A[i].a;
    		}
    	for(int i = 0; i < B.size(); ++i)
    		{
    		if(h < B[i].a) return false;
    		h += B[i].b - B[i].a;
    		}
    	return true;
    	}
    int main()
    	{
    	freopen("backpark.in", "r", stdin), freopen("backpark.out", "w", stdout);
    	read(T);
    	while(T--)
    		{
    		A.clear(), B.clear();
    		read(n), read(v), h = v;
    		for(int i = 0; i < n; ++i)
    			{
    			thg x; read(x.a), read(x.b);
    			if(x.a < x.b) A.push_back(x);
    			else B.push_back(x);
    			}
    		sort(A.begin(), A.end(), cp1);
    		sort(B.begin(), B.end(), cp2);
    		puts(Jud() ? "Yes": "No");
    		}
    	fclose(stdin), fclose(stdout);
    	return 0;
    	}
    

     3.求数列的子序列和的前k大,降序输出

    每次取当前堆中最大,用这个最大区间更新新的小区间

    #include <set>
    #include <vector>
    #include <stdio.h>
    #include <string.h>
    #include <iostream>
    #include <algorithm>
    typedef long long LL;
    using namespace std;
    template<class Type>inline Type read()
    	{
    	Type x = 0; int c = getchar();
    	while(c < '0' || c > '9') c = getchar();
    	while(c >= '0' && c <= '9') x = x * 10 + c - 48, c = getchar();
    	return x;
    	}
    struct rng
    	{
    	int l, r;
    	bool operator < (const rng oth) const
    	{return (l == oth.l) ? (r < oth.r) : l < oth.l;}
    	bool operator == (const rng oth) const
    	{return l == oth.l && r == oth.r;}
    	};
    struct node
    	{
    	int l, r;
    	LL sum;
    	bool operator < (const node oth) const
    	{return sum < oth.sum;}
    	bool operator == (const node oth) const
    	{return sum == oth.sum;}
    	}tmp;
    set<rng> h;
    vector<node> A;
    int n, a[100001], K;
    int main()
    	{
    	freopen("ksum.in", "r", stdin), freopen("ksum.out", "w", stdout);
    	n = read<int>(), K = read<int>();
    	tmp.l = 1, tmp.r = n;
    	for(int i = 1; i <= n; ++i) a[i] = read<int>(), tmp.sum += a[i];
    	A.push_back(tmp), h.insert((rng){1, n});
    	make_heap(A.begin(), A.end());
    	for(int i = 1; i <= K; ++i)
    		{
    		tmp = A.front(); pop_heap(A.begin(), A.end()), A.pop_back();
    		printf("%I64d ", tmp.sum);
    		int l = tmp.l, r = tmp.r - 1;
    		if(h.find((rng){l, r}) == h.end())
    			{
    			h.insert((rng){l, r});
    			A.push_back((node){l, r, tmp.sum - a[tmp.r]});
    			push_heap(A.begin(), A.end());
    			}
    		++l, ++r;
    		if(h.find((rng){l, r}) == h.end())
    			{
    			h.insert((rng){l, r});
    			A.push_back((node){l, r, tmp.sum - a[tmp.l]});
    			push_heap(A.begin(), A.end());
    			}
    		}
    	fclose(stdin), fclose(stdout);
    	return 0;
    	}
    
  • 相关阅读:
    cast() 函数进行类型转换
    '+' 拼接字符串引起的小事故
    shell统计ip访问情况并分析访问日志
    Windows 环境上域名配置
    WebApi中Route的作用
    Postman测试WebApi使用总结
    C# VS2017新建WepApi
    C# 反射总结
    winform--同一个项目窗体复制
    winform TextBox设置透明
  • 原文地址:https://www.cnblogs.com/keshuqi/p/7744294.html
Copyright © 2020-2023  润新知