POJ3617–Best Cow Line(贪心水题)
原题链接: POJ3617.
题目简述
给定长度为N的字符串S,要构造一个长度为N的字符串T。起初,T是一个空串,随后反复进行如下任意操作。
- 从S的头部删除一个字符,加到T的尾部
- 从S的尾部删除一个字符,加到T的尾部
标准输入:
第1行:单个整数:N
第2行:输入长度为N的字符串。
标准输出:
输出最小的字典串,每行80个。
示例输入:
6
A C D B C B
示例输出:
ABCBCD
贪心思路:
- 目的是要构造字典序尽量小的字符串T
从字典序的性质上看,无论T的末尾多大,只要前面部分的较小就可以。所以我们可以不断取S的开头和结尾字典序较小的加到T即可。
那么问题就在于S的开头和结尾字符相同还没有处理。在这种情况下,我们希望尽早的使用比较小的字符,所以就要比较下一个字符的大小。下一个字符也有可能相同,因此算法如下:
- 按照字典序比较S和将S反转后的字符串S’。
- 如果S比较小,就从S的开头取出一个字符,加到T的末尾。
- 如果S’比较小,就从S‘的末尾取出一个字符,加到T的末尾。
如果相同两个任选。
代码如下:
#include<iostream>
using namespace std;
const int N=1e6+10;
int n,cnt;
char s[N];
void slove()
{
//剩余的字符串为是S[a],S[a+1]……,S[b]
int a=0,b=n-1;
while(a<=b){
//将从左起和从右起的字符串比较
bool flag=false;//左边大于右边则为true
for(int i=0;a+i<=b;i++){
//左边大于右边则flag为true
if(s[a+i]<s[b-i]){
flag=true;
break;
}
//一定是else if,不是else。因为当相等的时候还要继续循环比较
else if(s[a+i]>s[b-i]){
break;
}
}
cnt++;//计算输出个数
if(flag) putchar(s[a++]);
else putchar(s[b--]);
if(cnt%80==0) cout<<endl;//控制格式
}
return ;
}
int main()
{
#ifndef ONLINE_JUDGE
freopen("in.txt", "r", stdin);
freopen("out.txt", "w", stdout);
#endif
cin>>n;
for(int i=0;i<n;i++) cin>>s[i];
slove();//调用函数
return 0;
}