贪心算法poj 3617,3069,3253

挑战程序设计竞赛

greedy problem

poj 3617 Best Cow Line

想法:先生成一个反着的字符串,(其实就是从两边开始找)先取出两边相比较小的字符串。当然这里有个问题,就是两边的头一个字符相同时,比较下一个字符,直到比较完整个字串为止,找到较小的那边的第一个字符加上。其实用strcmp就可以很好的解决上面描述的操作。
code:

#include <iostream>
#include <string>
#include <algorithm>
using namespace std;
int main(void){
    int n,pos1=0,pos2=0;
    cin>>n;
    char temp;
    string s,t,sRev;
    for(int i=0;i<n;i++){
        cin>>temp;
        sRev+=temp;
    }
    s=sRev;
    reverse(sRev.begin(),sRev.end());
    while(pos1+pos2<n){
        if(strcmp(&s[pos1],&sRev[pos2])<0){
            t+=s[pos1];
            pos1++;
        }
        else{
            t+=sRev[pos2];
            pos2++;
        }
    }
    for(int i=0;i<t.size();i++){
        cout<<t[i];
        if((i+1)%80==0&&i!=0){
            cout<<'\n';
        }
    }
}

poj 3069 Saruman’s Army.

想法:对于这题同样可以应用贪心的思想,我们尽量让选择的点尽可能的向右移,也就是在满足包含最左边需要的点的前提下寻找距离该点最远的点作为标记点。这样就可以满足最小化标记点数。
code:

#include<iostream>
#include<algorithm>
using namespace std;
int main(void){
    int r;
    while(cin>>r&&r!=-1){
        int n,markedPos,count=0,needLeft,pos=0;
        int point[1005];
        cin>>n;
        for(int i=0;i<n;i++){
            cin>>point[i];
        }
        sort(point,point+n);
        needLeft=point[pos];
        while(pos<n){
            while(point[pos]-r<=needLeft){
                pos++;
            }
            markedPos=point[pos-1];
            count++;
            while(point[pos]<=markedPos+r){
                pos++;
            }
            needLeft=point[pos];
        }
        cout<<count<<endl;
    }
}

poj 3253 Fence Repair

想法:讲道理这题我原来在vijos上见过,好像叫最小合并代价。。。反正从贪心的角度来考虑的话就是先合并比较小的,然后总是合并比较小的木块,这样就可以保证总代价最小,书上的考虑方法是用树来解决的,如果把分割的过程画成个树的话那么最后的代价就是每个最下面的子节点的大小*节点的深度。那么不难想我们只要让越小的越望下面放就行了,反过来从合成的角度来说的话就是每次合成较小的两个木块。
code.

#include<iostream>
#include<algorithm>
using namespace std;
long long wood[20005];
int main(void){
    int n;
    long long ans=0;
    cin>>n;
    for(int i=0;i<n;i++){
        cin>>wood[i];
    }
    sort(wood,wood+n);
    for(int i=0;i<n;i++){
        wood[i+1]+=wood[i];
        if(i!=n-1)
        ans+=wood[i+1];
        for(int j=i+2;j<n;j++){
            if(wood[j]<wood[j-1]){
                swap(wood[j],wood[j-1]);
            }
            else{
                break;
            }
        }
    }
    cout<<ans<<endl;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值