您的位置:首页 > 其它

贪心算法poj 3617,3069,3253

2017-08-05 15:15 239 查看

挑战程序设计竞赛

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;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息