想法:先生成一个反着的字符串,(其实就是从两边开始找)先取出两边相比较小的字符串。当然这里有个问题,就是两边的头一个字符相同时,比较下一个字符,直到比较完整个字串为止,找到较小的那边的第一个字符加上。其实用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'; } } }想法:对于这题同样可以应用贪心的思想,我们尽量让选择的点尽可能的向右移,也就是在满足包含最左边需要的点的前提下寻找距离该点最远的点作为标记点。这样就可以满足最小化标记点数。 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; } }想法:讲道理这题我原来在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; }