poj3617:Best Cow Line
题目描述
给定一个长度为n的字符串s,将s重排得到字符串t,使得字符串t的字典序最小,且只能使用下面两种操作
- 从s的头部取一个字符放在t末尾
- 从s的尾部取一个字符放在t末尾
分析
贪心策略
最直接的想法,比较s的头部字符和尾部字符,将较小的插入到t末尾。
但存在一个问题,当s头部字符和尾部字符相同时,就要比较头部第二个字符和尾部第二个字符,此时仍会出现同样的问题,就要一直比较下去...
基于上面的分析,每次插入时,比较s和其逆序s1的字典序大小,若s字典序较小,则选择s头部字符插入,反之则选择s尾部字符插入,若s和s1字典序也相同,选择头部尾部均可
代码
#include<stdio.h>
#include<iostream>
using namespace std;
const int MAXN = 3000; //注意数组大小
char s[MAXN], t[MAXN];
/**
* 判断s[left]-s[right]正序和反序的字典序大小
* @param left
* @param right
* @return true:正序小于反序,从left取元素
*/
bool Judge(int n, int left, int right){
for(int i = left, j = right; i < n, j >= 0; ++i, --j){
if(s[i] < s[j]){
return true;
}
else if(s[i] > s[j]){
return false;
}
}
return true;
}
int main(){
int n;
scanf("%d", &n);
for(int i = 0; i < n; ++i){
getchar();
scanf("%c", &s[i]);
}
int k = 0;
int left = 0;
int right = n - 1;
while(k < n){
if(Judge(n, left, right)){ //从left取
t[k++] = s[left++];
}
else{
t[k++] = s[right--];
}
}
int cnt = 0;
for(int i = 0; i < k; ++i){
putchar(t[i]);
++cnt;
if(cnt == 80){ //处理输出,每80个字符一行
putchar('\n');
cnt = 0;
}
}
putchar('\n');
return 0;
}