三周总结-贪心练习

1.寻找平面上的极大点:在一个平面上,如果有两个点(x,y),(a,b),如果说(x,y)支配了(a,b),这是指x>=a,y>=b;
用图形来看就是(a,b)坐落在以(x,y)为右上角的一个无限的区域内。
给定n个点的集合,一定存在若干个点,它们不会被集合中的任何一点所支配,这些点叫做极大值点。
编程找出所有的极大点,按照x坐标由小到大,输出极大点的坐标。
本题规定:n不超过100,并且不考虑点的坐标为负数的情况。
样例输入:
5
1 2 2 2 3 1 2 3 1 4
样例输出:
(1,4),(2,3),(3,1)
列点图示
拿题思想:在读完题时有一点迷惑,甚至不知道要干嘛,结果看了列图,输出的为在右边顶点的那些坐标;也就是当x值相同时,找y值最大的点,反之y值相同时,找x值最大的点。
遇到问题:此题困扰我的地方在于找出最值点的规律,和从小开始取点与从大开始取点转换。
最终解题步骤
1)建立数据结构储存输入的点坐标;
2)将输入的点进行排序,方便后续的找最大值点;
3)贪心思想就是它的y值比它右边(包括这一列)的点都要大,那么该点为极大点(但当x的值相等的点就得比较y的值最大那个为最值点)

#include <iostream>
#include <algorithm>
using namespace std;
struct point                 //建立数据结构储存点;
{
    int x;
    int y;
}p[100];
int cap(point a,point b)     //将点进行排序的规则;
{
    if(a.x!=b.x)
        return a.x<b.x;
    else return a.y<b.y;
}
int main()
{
    int n,i,s,d=0,mp[100];
    cin>>n;
    for(i=0;i<n;i++)
        cin>>p[i].x>>p[i].y;
    sort(p,p+n,cap);           //将点进行排序;
    for(s=0,i=n-1;i>=0;i--)
        {
            if(p[i].y>d)
                {
                    mp[s]=i;    //s用来记住为最值点的下角标;
                    s++;
                    d=p[i].y;
                }
        }
    for(i=s-1;i>0;i--)
          cout<<'('<<p[mp[i]].x<<','<<p[mp[i]].y<<')'<<',';
    cout<<'('<<p[mp[i]].x<<','<<p[mp[i]].y<<')'<<endl;
    return 0;
}

2.Pearl Pairing
描述
At Bessie’s recent birthday party, she received N (2 <= N <= 100,000; N%2 == 0) pearls, each painted one of C different colors (1 <= C <= N).

Upon observing that the number of pearls N is always even, her creative juices flowed and she decided to pair the pearls so that each pair of pearls has two different colors.

Knowing that such a set of pairings is always possible for the supplied testcases, help Bessie perform such a pairing. If there are multiple ways of creating a pairing, any solution suffices.

输入
Line 1: Two space-separated integers: N and C

*Lines 2…C + 1: Line i+1 tells the count of pearls with color i: C_i
输出
*Lines 1…N/2: Line i contains two integers a_i and b_i indicating that Bessie can pair two pearls with respective colors a_i and b_i.
样例输入
8 3
2
2
4
样例输出
1 3
1 3
2 3
3 2
拿题思想:此题就是给了你一些数目的珍珠,每个珍珠都有颜色,有相同的,也有不同的,需要最后输出每两个为一组的珍珠,且他们的颜色不相同,读到了这我想到了既然相同颜色的珍珠数各不相同,有多有少,那么我就让大的和次大的组合,然后再进行排序,在进行相同的操作;
遇到问题:发现通过上面的方法,不能像样列那样输出;
如何解决问题的:其实不用这样,因为输入珍珠时是颜色相同的放一起,那么只需要将第i个与第i+n/2个一起组合就行;
最终解题步骤
1)定义一个数组来储存珍珠的颜色;
2)将第i个与i+n/2个输出就行;

#include<iostream>
using namespace std;
int main(){

	int n,c,x,i,j,l=1;
	int a[100010];
	cin>>n>>c;
	for(i=1;i<=c;i++)
        {
            cin>>x;
            for(j=0;j<x;j++)      //对每个珍珠的颜色经行储存;
                {
                    a[l]=i;
                    l++;
                }
        }
    for(i=1;i<=n/2;i++)
        cout<<a[i]<<" "<<a[i+n/2]<<endl;
	return 0;

}

3.Crossing River
描述
A group of N people wishes to go across a river with only one boat, which can at most carry two persons. Therefore some sort of shuttle arrangement must be arranged in order to row the boat back and forth so that all people may cross. Each person has a different rowing speed; the speed of a couple is determined by the speed of the slower one. Your job is to determine a strategy that minimizes the time for these people to get across.

输入
The first line of the input contains a single integer T (1 <= T <= 20), the number of test cases. Then T cases follow. The first line of each case contains N, and the second line contains N integers giving the time for each people to cross the river. There won’t be more than 1000 people and nobody takes more than 100 seconds to cross.
输出
For each test case, print a line containing the total number of seconds required for all the N people to cross the river.
样例输入
1
4
1 2 5 10

样例输出
17
拿题思想:这是一个划船过河的问题,船只能最多载两个人一次,还得需要一个人划回去,而且两个人的时候,船划行速度等于最慢的那个,那么我最初的想法就是每次都是最快的那个和其他的人划,船由最快的划回来;就这样时间因该时最短的;
遇到问题:每次都是最快的和其他的时间总和到底是不是最短的时间;还是最快的和次快的划过去,最快的再把船划回来,然后和最慢的划过去;
解决问题:只需将这两种方法算出来的时间进行比较,取最小的那个就行了;一个是a[n-1]+a[0]+a[n-2]+a[0];宁外一个时a[1]+a[0]+a[n-1]+a[1];
最终解题步骤
1)用一个数组储存每个人划船的时间,并用sort函数排序;
2)讨论人数不同的表达情况;
3)最终表达出最短的时间;

源代码
	#include <iostream>
#include <cmath>
#include <algorithm>
using namespace std;

int main()
{
    int t,n,a[1000],sum,i;
    cin>>t;
    while(t--)
        {
            cin>>n;
            sum=0;
            for(i=0;i<n;i++)
                cin>>a[i];
            sort(a,a+n);      //排序将划船时间进行从小到大排序;
            while(n>3)
                {
                    sum=min(sum+a[n-1]+a[0]+a[n-2]+a[0],sum+a[1]+a[0]+a[n-1]+a[1]);
                    n-=2;
                }
            if(n==3) sum+=a[0]+a[1]+a[2];      //有限n的情况;
            else if(n==2) sum+=a[1];
            else sum+=a[0];
            cout<<sum<<endl;
        }
    return 0;
}

4.Sunscreen;
描述
To avoid unsightly burns while tanning, each of the C (1 <= C <= 2500) cows must cover her hide with sunscreen when they’re at the beach. Cow i has a minimum and maximum SPF rating (1 <= minSPF_i <= 1,000; minSPF_i <= maxSPF_i <= 1,000) that will work. If the SPF rating is too low, the cow suffers sunburn; if the SPF rating is too high, the cow doesn’t tan at all.

The cows have a picnic basket with L (1 <= L <= 2500) bottles of sunscreen lotion, each bottle i with an SPF rating SPF_i (1 <= SPF_i <= 1,000). Lotion bottle i can cover cover_i cows with lotion. A cow may lotion from only one bottle.

What is the maximum number of cows that can protect themselves while tanning given the available lotions?

输入

  • Line 1: Two space-separated integers: C and L

  • Lines 2…C+1: Line i describes cow i’s lotion requires with two integers: minSPF_i and maxSPF_i

  • Lines C+2…C+L+1: Line i+C+1 describes a sunscreen lotion bottle i with space-separated integers: SPF_i and cover_i

输出
A single line with an integer that is the maximum number of cows that can be protected while tanning

样例输入
3 2
3 10
2 5
1 5
6 2
4 1
样例输出
2
拿题思想:这是一个跟牛涂霜的问题,需要保证要让最多的牛被保护的情况下还得晒黑,这就需要霜的选择要在牛spf值的min和max之间,那么我就想将牛的spf信息储存到结构体数组中,方便取用,将每个霜的信息储存到宁一个结构体数组中然后分别进行排序,将合适的霜涂给合适的牛;
最终解体步骤
1)建立两个结构体数组分别储存牛和霜的信息;
2)将牛的结构体数组进行排序,将min大的排在前面;将霜进行排序由spf从高到低排;
3)开始从结构体数组牛的和霜的spf进行比较,如果min<=spf<=max则将对应的霜涂给对应的牛;否则这头牛不涂;

#include <iostream>
#include <algorithm>
using namespace std;
struct niu                //结构体储存牛的信息,min,max;
{
    int min;
    int max;
}a[3000];
struct fs                 //结构体储存霜的spf和瓶数;
{
    int spf;
    int num;
}b[3000];
bool cmp1(niu x,niu y)     //排序的规则;
{
    return x.min>y.min;
}
bool cmp2(fs x,fs y)
{
    return x.spf>y.spf;
}
int main()
{
    int c,l,i,j,tou=0;
    cin>>c>>l;
    for(i=0;i<c;i++)
        cin>>a[i].min>>a[i].max;
    sort(a,a+c,cmp1);
    for(i=0;i<l;i++)
        cin>>b[i].spf>>b[i].num;
    sort(b,b+l,cmp2);
    for(i=0;i<c;i++)
        for(j=0;j<l;j++)
            {
                if(a[i].min<=b[j].spf&&a[i].max>=b[j].spf&&b[j].num)
                    {
                        tou++;
                        b[j].num--;
                        break;
                    }
            }
    cout<<tou<<endl;
    return 0;
}

总结经过这两周多一点的时间对贪心算法的学习即练习,发现自己的能力还是有些不足,对贪心算法的理解不够透彻,甚至在一些题的面前毫无头绪,不过老师说过多花时间去琢磨,有一些题经过琢磨之后还是产生了一些想法,即对贪心算法的认识和运用有了进步。虽然进入了动态规划的学习,但我想对贪心算法和之前的递归算法的熟悉和运用不能停止。

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值