20200321贪心训练总结

1.Cinema Line
The new “Die Hard” movie has just been released! There are n people at the cinema box office standing in a huge line. Each of them has a single 100, 50 or 25 ruble bill. A “Die Hard” ticket costs 25 rubles. Can the booking clerk sell a ticket to each person and give the change if he initially has no money and sells the tickets strictly in the order people follow in the line?

Input
The first line contains integer n (1 ≤ n ≤ 105) — the number of people in the line. The next line contains n integers, each of them equals 25, 50 or 100 — the values of the bills the people have. The numbers are given in the order from the beginning of the line (at the box office) to the end of the line.

Output
Print “YES” (without the quotes) if the booking clerk can sell a ticket to each person and give the change. Otherwise print “NO”.

Examples
Input
4
25 25 50 50
Output
YES
Input
2
25 100
Output
NO
Input
4
50 50 25 25
Output
NO
本题实际上是一个找零问腿,初始状态纸币数量为0,每当有人来付款时,若此人付的纸币面值不是25元,就需要找零。若面值为100,则需找零一张50元及一张25元纸币或共找回三张25元纸币,付款面值为50元则需找回25元纸币,我们只需观察待找回的纸币数量是否充足即可。
AC代码

#include<iostream>
#include<bits/stdc++.h>
using namespace std;
int a[4],n,s,i;
bool flag=true;
int main()
{
    cin>>n;
    for(i=1;i<=n;i++)
    {
        cin>>s;
        if(s==25) a[0]++;
        else if(s==50)
        {
            a[0]--;
            a[1]++;
        }
        else if(s==100)
        {
            if(a[1]>=1)
            {
                a[1]--;
                a[0]--;
            }
            else a[0]-=3;
        }
        if(a[0]<0) flag=false;
    }
    if(flag) cout<<"YES";
    else cout<<"NO";
    return 0;
}

2.最短前缀
描述
一个字符串的前缀是从该字符串的第一个字符起始的一个子串。例如 “carbon"的字串是: “c”, “ca”, “car”, “carb”, “carbo”, 和 “carbon”。注意到这里我们不认为空串是字串, 但是每个非空串是它自身的字串. 我们现在希望能用前缀来缩略的表示单词。例如, “carbohydrate” 通常用"carb"来缩略表示. 现在给你一组单词, 要求你找到唯一标识每个单词的最短前缀
在下面的例子中,“carbohydrate” 能被缩略成"carboh”, 但是不能被缩略成"carbo" (或其余更短的前缀) 因为已经有一个单词用"carbo"开始
一个精确匹配会覆盖一个前缀匹配,例如,前缀"car"精确匹配单词"car". 因此 “car” 是 "car"的缩略语是没有二义性的 , “car”不会被当成"carriage"或者任何在列表中以"car"开始的单词.
输入
输入包括至少2行,至多1000行. 每行包括一个以小写字母组成的单词,单词长度至少是1,至多是20.
输出
输出的行数与输入的行数相同。每行输出由相应行输入的单词开始,后面跟着一个空格接下来是相应单词的没有二义性的最短前缀标识符。
样例输入
carbohydrate
cart
carburetor
caramel
caribou
carbonic
cartilage
carbon
carriage
carton
car
carbonate
样例输出
carbohydrate carboh
cart cart
carburetor carbu
caramel cara
caribou cari
carbonic carboni
cartilage carti
carbon carbon
carriage carr
carton carto
car car
carbonate carbona
本题实质是找出该单词与其他单词不同的最短字符串,我认为解此题最重要的是了解strstr函数的适用范围和使用方法。strstr函数即为判断两字符串中前者是否为后者的字串。这样一来,最短字串问题就比较容易的解决了。
AC代码

#include <iostream>
#include <string>
#include <cstring>
#include <algorithm>
#include<bits/stdc++.h>
#define N 1005
using namespace std;
typedef long long ll;
string s[N];
char str[25];
int main()
{
    int n=0;
    while(cin>>s[n]) n++;   
    int i,j,k;
    for(i=0;i<n;i++)        
    {
        for(j=0;j<s[i].length();j++)
        {
            memset(str,0,sizeof(str)); 
            for(k=0;k<=j;k++)
            str[k]=s[i][k];
            str[k]='\0';
            for(k=0;k<n;k++)
            {
                if(k==i) continue;
                if(strstr(s[k].c_str(),str)==s[k].c_str())
                break;
            }
            if(k==n) 
            {
                cout<<s[i]<<" "<<str<<endl;
                break;
            }
        }
        if(j==s[i].length()) cout<<s[i]<<" "<<s[i]<<endl;
    }
    return 0;
}

3.Standard Free2Play
You are playing a game where your character should overcome different obstacles. The current problem is to come down from a cliff. The cliff has height h, and there is a moving platform on each height x from 1 to h.

Each platform is either hidden inside the cliff or moved out. At first, there are n moved out platforms on heights p1,p2,…,pn. The platform on height h is moved out (and the character is initially standing there).

If you character is standing on some moved out platform on height x, then he can pull a special lever, which switches the state of two platforms: on height x and x−1. In other words, the platform you are currently standing on will hide in the cliff and the platform one unit below will change it state: it will hide if it was moved out or move out if it was hidden. In the second case, you will safely land on it. Note that this is the only way to move from one platform to another.

Your character is quite fragile, so it can safely fall from the height no more than 2. In other words falling from the platform x to platform x−2 is okay, but falling from x to x−3 (or lower) is certain death.

Sometimes it’s not possible to come down from the cliff, but you can always buy (for donate currency) several magic crystals. Each magic crystal can be used to change the state of any single platform (except platform on height h, which is unaffected by the crystals). After being used, the crystal disappears.

What is the minimum number of magic crystal you need to buy to safely land on the 0 ground level?

Input
The first line contains one integer q (1≤q≤100) — the number of queries. Each query contains two lines and is independent of all other queries.

The first line of each query contains two integers h and n (1≤h≤109, 1≤n≤min(h,2⋅105)) — the height of the cliff and the number of moved out platforms.

The second line contains n integers p1,p2,…,pn (h=p1>p2>⋯>pn≥1) — the corresponding moved out platforms in the descending order of their heights.

The sum of n over all queries does not exceed 2⋅105.

Output
For each query print one integer — the minimum number of magic crystals you have to spend to safely come down on the ground level (with height 0).

Example
Input
4
3 2
3 1
8 6
8 7 6 5 3 2
9 6
9 8 5 4 3 1
1 1
1
Output
0
1
2
0
本题大意为一个人站在悬崖上,通过扳动按钮到达高度-1的下一平台,但搬动按钮会使下一平台的状态改变(平台状态有裸露在外和隐藏在悬崖中两种),输入中给出裸露在外的平台的高度,此人可以承受的最大极限为2个单位的高度,若超过两个单位高度还未有裸露在外的悬崖,则需要购买宝石,一个宝石可以改变任何一个平台的状态,问最少需购买几个宝石才可成功到达悬崖底。
理解题意后,题目就相对来讲比较容易解决了。我们只需要判断下边一个平台的状态即可。
AC代码

#include<iostream>
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
ll a[200005],q,h,n,sum,ans;
int main()
{
    cin>>q;
    while(q--)
    {
        sum=0;
        ans=2;
        memset(a,0,sizeof(a));
        cin>>h>>n;
        for(int i=1;i<=n;i++)
            cin>>a[i];
        a[0]=-1;
        for(int i=2;i<=n;i++)
        {
            if(a[i]==a[i-1]-1)
                ans++;
            else
            {
                if(ans%2==1)
                sum++;
                ans=1;
            }
            if(i==n&&ans%2==1&&a[i]!=1)
                sum++;
        }
        cout<<sum<<endl;
    }
    return 0;
}

4.电池的寿命
描述
小S新买了一个掌上游戏机,这个游戏机由两节5号电池供电。为了保证能够长时间玩游戏,他买了很多5号电池,这些电池的生产商不同,质量也有差异,因而使用寿命也有所不同,有的能使用5个小时,有的可能就只能使用3个小时。显然如果他只有两个电池一个能用5小时一个能用3小时,那么他只能玩3个小时的游戏,有一个电池剩下的电量无法使用,但是如果他有更多的电池,就可以更加充分地利用它们,比如他有三个电池分别能用3、3、5小时,他可以先使用两节能用3个小时的电池,使用半个小时后再把其中一个换成能使用5个小时的电池,两个半小时后再把剩下的一节电池换成刚才换下的电池(那个电池还能用2.5个小时),这样总共就可以使用5.5个小时,没有一点浪费。现在已知电池的数量和电池能够使用的时间,请你找一种方案使得使用时间尽可能的长。

输入
输入包含多组数据。每组数据包括两行,第一行是一个整数N (2 ≤ N ≤ 1000),表示电池的数目,接下来一行是N个正整数表示电池能使用的时间。
输出
对每组数据输出一行,表示电池能使用的时间,保留到小数点后1位。
样例输入
2
3 5
3
3 3 5

样例输出
3.0
5.5
本题可采用贪心策略解决,无需考虑每个电池的使用情况,只需考虑使用时间最长的电池能否被使用完全即可。
AC代码

#include<iostream>
#include<iomanip>
#include<cstdio>
#include<algorithm>
using namespace std;
int main()
{
    int n,a[1005];
    while(cin>>n)
    {
        int Max=-1,sum=0;
        for(int i=1;i<=n;i++)
        {
            cin>>a[i];
            sum+=a[i];
            if(Max<a[i]) Max=a[i];
        }
        if((sum-Max)<Max)
            cout<<fixed<<setprecision(1)<<(sum-Max)*1.0<<endl;
        else
            cout<<fixed<<setprecision(1)<<(sum-2*Max)*1.0/2+Max<<endl;
    }
    return 0;
}

5。Ride to the Office
描述
Many staff of are living in a place called MZone, far from their office( 4.5 km ). Due to the bad traffic, many staff choose to ride a bike.

We may assume that all the people except “Weiwei” ride from home to office at a fixed speed. Weiwei is a people with a different riding habit – he always tries to follow another rider to avoid riding alone. When Weiwei gets to the gate of MZone, he will look for someone who is setting off to the Office. If he finds someone, he will follow that rider, or if not, he will wait for someone to follow. On the way from his home to office, at any time if a faster student surpassed Weiwei, he will leave the rider he is following and speed up to follow the faster one.

We assume the time that Weiwei gets to the gate of MZone is zero. Given the set off time and speed of the other people, your task is to give the time when Weiwei arrives at his office.

输入
There are several test cases. The first line of each case is N (1 <= N <= 10000) representing the number of riders (excluding Weiwei). N = 0 ends the input. The following N lines are information of N different riders, in such format:

Vi [TAB] Ti

Vi is a positive integer <= 40, indicating the speed of the i-th rider (kph, kilometers per hour). Ti is the set off time of the i-th rider, which is an integer and counted in seconds. In any case it is assured that there always exists a nonnegative Ti.
输出
Output one line for each case: the arrival time of Weiwei. Round up (ceiling) the value when dealing with a fraction.
样例输入
4
20 0
25 -155
27 190
30 240
2
21 0
22 34
0

样例输出
780
771
本题与上题相似,无需考虑weiwei中途跟多少人一起走过,只需考虑他最终与谁一起到达的终点。而他到达终点的时间即为与他一起到达终点的人全程花费的时间加上出发时间。

#include<iostream>
#include<cstdio>
#include<algorithm>
#include<cmath>
#define INF 0x3f3f3f 
using namespace std;
int n,ans,v,t,i;
int main()
{
    while(cin>>n)
    {
        if(n==0) break;
        ans=INF;
        for(i=1;i<=n;i++) {
            cin>>v>>t;
            if(t >= 0) {
                int Min = ceil(t + 4.5/v * 3600);
                ans=min(ans,Min);
            }
        }
        cout<<ans<<endl;
    }
    return 0;
}

6.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
本题相对比较复杂,每次船只能送两个人到对岸,所需时间为二者中时间较慢的人需要的时间,送到对岸的两人还需回来一个人把船开回来继续运送客人。共两种思路(当人数>=4时),第一种为最快的两个人先过河(t+=t2),最快的人回来(t+=t1)接着未过河的人中最慢的两个人过河(t+=ts),第二快的人回来(t+=t2),这样最慢的两个人就成功过河,所需时间为t=t1+2t2+ts。第二种思路为最快的人分两次把最慢的人和倒数第二慢的人送过
河,然后自己回来,所需时间为t=2
t1+t(s-1)+ts,然后判断这两种方法哪种方法所需时间最短即可。
AC代码如下

#include<iostream>
#include<bits/stdc++.h>
#include<algorithm>
using namespace std;
int t,n,a[1005];
int cross(int s);
int main()
{
    cin>>t;
    for(int i=1;i<=t;i++)
    {
        memset(a,0,sizeof(a));
        cin>>n;
        for(int j=1;j<=n;j++)
            cin>>a[j];
        sort(a+1,a+1+n);
        cout<<cross(n)<<endl;
    }
    return 0;
}
int cross(int s)
{
    if(s==1) return a[1];
    else if(s==2) return a[2];
    else if(s==3) return a[1]+a[2]+a[3];
    else
    {
        int t1=a[1]+2*a[2]+a[s];
        int t2=2*a[1]+a[s-1]+a[s];
        return min(t1,t2)+cross(s-2);
    }
}

7.拼点游戏
描述
C和S两位同学一起玩拼点游戏。有一堆白色卡牌和一堆蓝色卡牌,每张卡牌上写了一个整数点数。C随机抽取n张白色卡牌,S随机抽取n张蓝色卡牌,他们进行n回合拼点,每次两人各出一张卡牌,点数大者获得三颗巧克力,小者获得一颗巧克力,如果点数相同,每人各得二颗巧克力,使用过的卡牌不得重复使用。已知C和S取到的卡牌点数,请编程计算S最多和最少能得到多少颗巧克力。

输入
输入包含多组测试数据。
每组测试数据的第一行是一个整数n(1<=n<=1000),接下来一行是n个整数,表示C抽到的白色卡牌的点数,下一行也是n个整数,表示S抽到的蓝色卡牌的点数。
输入的最后以一个0表示结束。
输出
对每组数据,输出一行,内容是两个整数用空格格开,分别表示S最多和最少可获得的巧克力数。
样例输入
3
92 83 71
95 87 74
2
20 20
20 20
2
20 19
22 18
0
样例输出
9 5
4 4
4 4
这个题和经典例题田忌赛马的大致解题思路相似,田忌赛马,但这个题我认为我写的比较复杂,我计算了两遍,但目前还没有想到更好的思路,先记录下这个相对复杂的思路,等后续有了好思路再进行更新吧。

#include<iostream>
#include<algorithm>
#include<cstring>
using namespace std;
int Maxc,Maxs,Minc,Mins,sum,n,c[1005],s[1005],ans,i;
bool cmp(int p,int q)
{
    return p>q;
}
int main()
{
    while(cin>>n)
    {
        if(n==0) break;
        memset(c,0,sizeof(c));
        memset(s,0,sizeof(s));
        for(i=1;i<=n;i++)
            cin>>c[i];
        for(i=1;i<=n;i++)
            cin>>s[i];
        sort(c+1,c+1+n,cmp);
        sort(s+1,s+1+n,cmp);
        Maxc=1;
        Maxs=1;
        Minc=n;
        Mins=n;
        sum=0;
        while(Mins>=Maxs&&Minc>=Maxc)
        {
            if(s[Maxs]>c[Maxc])
            {
                Maxs++;
                Maxc++;
                sum+=3;
            }
            else if(s[Mins]>c[Minc])
            {
                Mins--;
                Minc--;
                sum+=3;
            }
            else if(s[Mins]==c[Maxc])
            {
                Mins--;
                Maxc++;
                sum+=2;
            }
            else
            {
               sum++;
               Maxc++;
               Mins--;
            }
        }
        cout<<sum<<" ";
        Maxc=1;
        Maxs=1;
        Minc=n;
        Mins=n;
        sum=0;
        while(Mins>=Maxs&&Minc>=Maxc)
        {
            if(c[Maxc]>s[Maxs])
            {
                Maxc++;
                Maxs++;
                sum+=3;
            }
            else if(c[Minc]>s[Mins])
            {
                Minc--;
                Mins--;
                sum+=3;
            }
            else if(c[Minc]==s[Maxs])
            {
                Minc--;
                Maxs++;
                sum+=2;
            }
            else
            {
               sum++;
               Maxs++;
               Minc--;
            }
        }
        cout<<4*n-sum<<endl;
    }
    return 0;
}
发布了8 篇原创文章 · 获赞 12 · 访问量 179

猜你喜欢

转载自blog.csdn.net/weixin_46434074/article/details/105001392