五一假期简单贪心十练之前五练

来源:互联网 发布:ssh 服务默认端口为 编辑:程序博客网 时间:2024/04/28 16:50

POJ 3617

题意:长度为N的串S偶早字典序最小的长度为N的串T,要么从S的头部删除字符加入T要么从S的尾部删除加入T

贪心策略:每一次比较头和尾的字典序大小,每次取小的,更新长度和首尾位置。

#include<cstdio>#include<cstring>#include<iostream>#include<cmath>#include<algorithm>using namespace std;char s[2005];int n;void slove(){    int a=0;    int b=n-1;    int co=0;    while(a<=b)    {        int flag=0;        for(int i=0;a+i<=b;i++)        {            if(s[a+i]<s[b-i])            {                flag=1;                break;            }            else if(s[a+i]>s[b-i])            {                flag=0;                break;            }        }        if(flag==1)        {            putchar(s[a++]);        }        else        {            putchar(s[b--]);        }        co++;        if(co==80)        {            putchar('\n');            co=0;        }    }    putchar('\n');}int main(){    while(cin>>n)    {        for(int i=0;i<n;i++)        {            cin>>s[i];        }        slove();    }    return 0;}
POJ 3069

题意:N个点,给其中i个坐上标记,要让其距离为R的区域中都有被标记的点,求最小的标记点的个数。

贪心策略:从最左边开始扫描,让其距离为R的点的区域要有被标记的点,所以就是找最右侧的点,找到后看最右侧的点能覆盖到其右边的哪个点,然后从该点的下一个点作为

                    新的起点进行扫描直到扫完全部的点。

#include<cstdio>#include<cstring>#include<cmath>#include<iostream>#include<algorithm>using namespace std;int n;int r;int x[1005];void slove(){    sort(x,x+n);    int i=0;    int ans=0;    while(i<n)    {        int s=x[i++];//最左位置        while(i<n&&x[i]<=s+r)        {            i++;        }        int p=x[i-1];//找到新要标记的点        while(i<n&&x[i]<=p+r)        {             i++;//一直找直到找到超出距离的        }        ans++;//累加    }    cout<<ans<<endl;}int main(){    while(cin>>r>>n)    {        if(r==-1&&n==-1)            return 0;        for(int i=0;i<n;i++)        {            cin>>x[i];        }        slove();    }    return 0;}

POJ 2376

题意:选取最少的牛去工作,然后覆盖所有的时间

思路:按照左端点升序排列,相同的按照右端点降序排列,其余蛮类似于HDU的今年暑假不AC的思路。

#include<cstdio>#include<cstring>#include<cmath>#include<iostream>#include<algorithm>using namespace std;struct node{int x;int y;}a[25005];bool cmp(node a,node b){    if(a.x!=b.x)        return a.x<b.x;    else        return a.y>b.y;}int main(){    int n,t;    while(scanf("%d%d",&n,&t)!=EOF)    {        for(int i=0;i<n;i++)        {            scanf("%d%d",&a[i].x,&a[i].y);        }        sort(a,a+n,cmp);       int ans=0;       int i=0;       int temp=0;       int j;       while(temp<t&&i<n)       {          int top=temp;          if(a[i].x>temp+1)          {              printf("-1\n");              return 0;          }          while(i<n&&a[i].x<=temp+1)          {             // cout<<temp<<endl;              top=max(top,a[i].y);              i++;          }          temp=top;           ans++;       }       if(temp<t)       {           printf("-1\n");       }       else       {           printf("%d\n",ans);       }    }    return 0;}

POJ 1328

题意:平面上有一些点,现要求用一些圆心在x轴上的圆(雷达)来覆盖这些点,问最少需要多少雷达。

思路:额这题一开始不会啊,看了别人的思路,求每个点所构成的圆与X轴的左右交点,然后按照左交点的升序排列,若A圆右交点,在B圆左交点右侧,那么B被A包含,若A圆

           左交点在B圆右交点右侧,那必然不被包含,按着这个思路去求最少要多少个雷达。

#include<cstdio>#include<cstring>#include<cmath>#include<iostream>#include<algorithm>using namespace std;struct node{double l;double r;}p[2005];bool cmp(node a,node b){    return a.l<b.l;}int main(){    int n;    double r;    int Case=0;    while(cin>>n>>r)    {        if(n==0&&r==0)            return 0;        int flag=0;        for(int i=0;i<n;i++)        {            double a,b;            cin>>a>>b;            if(abs(b)>r)            {                flag=1;            }            else            {                p[i].l=a-sqrt(r*r-b*b);                p[i].r=a+sqrt(r*r-b*b);//左右交点            }        }        cout << "Case " << ++Case << ": ";        int ans;        if(flag==1)        {            cout<<-1<<endl;        }        else        {            sort(p,p+n,cmp);            node temp;            ans=1;            temp=p[0];            for(int i=1;i<n;i++)            {                if(p[i].l>temp.r)                {                    ans++;                    temp=p[i];                }                else if(p[i].r<temp.r)                {                    temp=p[i];                }            }            cout<<ans<<endl;        }    }    return 0;}
POJ 3190

题意:一些奶牛要在指定的时间内挤牛奶,而一个机器只能同时对一个奶牛工作。给你每头奶牛的指定时间的区间,问你最小需要多少机器。

贪心策略:唔,这个要用到新技能,优先队列,里面以已经开始挤奶的奶牛的结束时间早为优先。然后每次只需要检查当前是否有奶牛的挤奶工作已经完成的机器即可,

                    若有,则换那台机器进行工作。若没有,则加一台新的机器。新技能还是不熟练。。还是得再找几题练手。。。

#include<cstdio>#include<cstring>#include<cmath>#include<iostream>#include<algorithm>#include<queue>using namespace std;struct node{int s;int e;int t;}a[50005];int n;bool operator <(node a,node b ){    return a.e>b.e;}bool cmp(node a,node b){    return a.s<b.s;}priority_queue<node>q;int num[50005];int main(){    while(cin>>n)    {        for(int i=1;i<=n;i++)        {            cin>>a[i].s>>a[i].e;            a[i].t=i;        }        sort(a+1,a+n+1,cmp);        int ans=1;            while(!q.empty())                  q.pop();            q.push(a[1]);            num[a[1].t]=ans;            for(int i=2;i<=n;i++)            {                node temp=q.top();                if(temp.e<a[i].s)                {                    num[a[i].t]=num[temp.t];                    q.pop();                    q.push(a[i]);                }                else                {                    num[a[i].t]=++ans;                    q.push(a[i]);                }            }        cout<<ans<<endl;        for(int i=1;i<=n;i++)        {            cout<<num[i]<<endl;        }    }    return 0;}



0 0
原创粉丝点击