贪心第二周小总结

本周的贪心算法的代码基本在听完课后把保存的进行了修改,发现自己原本的代码是这么的麻烦。
首先是本周积累知识
下标储存;举例寻找规则(公式);两个问题合为一个
首先是删数问题,一开始认为删除当中最大的就可以,之后举例发现不行。然后经过多次举例发现在此类数字串中,如果删去的是第一个递减区间的第一个数就可以尽可能地控制它,也就是将其前面较大的删去,让后面较小的顶上。
代码实现环节中要用size计算长度,以便将其变短。
PS:使用string类最好,因为长度可以任意输入,但截止到空字符。

#include<iostream>
using namespace std;
int main()
{
    int n;
    cin>>n;
    while(n--)
    {
        string a;
        int k;
        cin>>a>>k;
        int len=a.size();
        while(k--)
        {
            for(int i=0; i<len; i++)
                if(a[i]>a[i+1]||i==len-1)
                {
                    a.erase(i,1);
                    break;
                }
        }
        cout<<a<<endl;

    }
}

第二题是寻找平面上的极大点
本题的意思我也是读了很多遍才理解,本质就是如果大于其y值得都在左边,小于其y值得都在右边,即为最大值。
最好的方式就是用struct语句输入坐标点。
然后将其x从小到大排序,x相同的点按照y坐标从小到大排序。如此一来在排序内就形成了一个个小区域,在小区域内y最大就为极大点,已知最后一个为极大点,向前推进,如果出现第一个x大于后面的极大点x即为第二个极大点。

#include<iostream>
#include<algorithm>
#include<stdio.h>
using namespace std;
struct point
{
    int x,y;
};
bool cmp(point a,point b)
{
    if(a.x!=b.x)
		return a.x<b.x;
	else
        return a.y<b.y;
}
int main()
{
    point a[110];
    int n;
    int i;
    cin>>n;
    for(i=1;i<=n;i++)
    {
        cin>>a[i].x>>a[i].y;
    }
    sort(a+1,a+n+1,cmp);
    int max=0;
    int t=0;
    int b[110];
    for(i=n;i>=1;i--)
    {
        if(a[i].y>max)
        {
            t++;
            b[t]=i;
            max=a[i].y;
        }
    }
    for(i=t;i>1;i--)
	{
		printf("(%d,%d),"a[b[i]].x,a[b[i]].y);
	}
	printf("(%d,%d)",a[b[i]].x,a[b[i]].y);
    return 0;
}

第三题为拼点游戏
具体类型如同田忌赛马,自己最好的打不过对方的最好的就用最差的消耗掉,然后比第二好的。
本题思路是先判断自己最好的是否能打过对方的最好的,如果不能,就看自己最小的是否能打过对方最小的,如果不能,就看自己最小的能否打过对方最好的,最后用自己最小的消耗掉对方最好的。
本体本质即为能赢就赢。
ps:此题陷阱是求一个最大,一个最小。
求最大写完之后,发现写不出来最求最小,之后老师讲了,都求最大才恍然大悟,用最大减去最小就行。本题一直wrong。

#include<iostream>
#include<algorithm>
using namespace std;
int a[1010], b[1010];
int n;
int solve(int a[], int b[])
{
    int choco= 0;
    int begina= 0, enda= n-1, beginb = 0, endb= n-1;
    while (begina<=enda&&beginb<=endb)
    {
        if (b[endb] > a[enda])
        {
            endb--;
            enda--;
            choco+= 3;
        }
        else if (b[beginb ] > a[begina])
        {
            begina++;
            beginb ++;
            choco += 3;
        }
        else if (b[endb] == a[enda])
        {
            beginb ++;
            enda--;
            choco+= 2;
        }
        else
        {
            enda--;
            beginb ++;
            choco++;
        }
    }
    return choco;
}
int main()
{
    while (cin>>n&&n!=0)
    {
        for (int i = 0; i< n; i++)
            cin >> a[i];
        for (int i = 0; i< n; i++)
            cin >> b[i];
        sort(a, a + n);
        sort(b, b + n);
        int max=solve(a, b);
        int min=4*n-solve(b,a);
        cout<<max <<' '<<min<<endl;

    }
    return 0;
}

第四个问题为过河问题
总的来说有两个方法,首先是最快的挨个送,第二个就是,按照头头尾尾的方式送之后头尾再送。t[0]+2t[1]+t[n-1];2t[0]+t[n-2]+t[n-1]不断比较这两个当中的最小的就可以
ps:一定要判断还剩几个人,因为公式不支持低于三人的,应当另行计算。

#include<iostream>
#include<algorithm>
using namespace std;
int main()
{
    int a[1010],t,n,sum;
    cin>>t;
    while(t--)
    {
        cin>>n;
        sum=0;
        for(int i=0; i<n; i++)
            cin>>a[i];
        sort(a,a+n);
        while(n>3)  
        {  
            sum=min(sum+a[1]+a[0]+a[n-1]+a[1],sum+a[n-1]+a[0]+a[n-2]+a[0]);  
            n-=2;  
        }  

        if(n==3)
            sum+=a[0]+a[1]+a[2];
        else if(n==2)
            sum+=a[1];
        else
            sum+=a[0];
        cout<<sum<<endl;
    }
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值