zoukankan      html  css  js  c++  java
  • Best Cow Line 解题报告

    1. 题目链接: http://poj.org/problem?id=3617
    2. 题意: 已知一段长度为N的字符串,让你构造一个字典序最小的字符串.构造的规则如下:如果原始字符串的头部 < 原始字符串的尾部,则从原始字符串的头部删除该字符添加到新的字符串的一个字符;如果头部 > 尾部则删除尾部的字符添加到新字符串中.
    3. 解题思路:首先用两个索引记录首尾的位置,然后依次比较两者的值,若头部的值小则头部索引+1向后移动一位,若尾部的值小则尾部索引-1向前移动一位,这是当两个位置的值不一样的情况下的比较,也比较简单. 但是复杂的情况就是两者的值相等的情况,我看的参考书是《挑战程序设计竞赛》第2版人民邮电出版社,这是翻译的日本人写的一本书,书中讲到这个问题时,解释为两者相等时随便选前后皆可,而且书中给出的代码中也没分析两者的情况,在很多的blog中有人也说可以随便选取.   但是仔细想想并非如此!!!!  就拿书中给出的这个题的例子分析, 原始串为"ACDBCB" 去除首尾的A和B后就剩下 "CDBC",若先选择首部的C 则剩下的4个字母的选择顺序为"CCBD",若选择尾部的C则剩下的4个字母的选择顺序为"CBCD" ,由此可见并不是随便选择的. 很显然如果两者的值相同的时候,必须继续比较两者的下一位的大小,但是要保证首部的索引要小于或等于尾部的索引!所以此题的难处就在于此,分清楚这个问题,此题就引刃而解了.但是分析下一位的时候可能会出现哪几种情况呢? 1 头部小选择头部 2 尾部小选择尾部 3 头尾继续相等,继续比较下一位. 但是注意极限状态,当首尾的索引相等的情况,说明从开始相等的部分开始是对称的(此时两个的索引是同一个值了,所以是奇数个的对称),既然有奇数个的对称就应该有偶数的对称(ACDDCB)次数会出现头尾的索引会交叉,当然是用另外的变量来代替(程序中的left 和right).所以此题就是要理清出具体的情况分类.而且这题是基于贪心策略的喔!每次选择最优的值呀!
    4. 解题代码:  下面的是我自己的代码,跟很多牛人的blog的代码在算法简便性上还是有很大差距,仅供参考(通过提交的结果看耗时太大还有待优化).
       1 #include <stdio.h>
       2 #include <stdlib.h>
       3 int min(int x,int y)
       4 {
       5     if(x < y)
       6         return x;
       7     else
       8         return y;
       9 }
      10 int main()
      11 {
      12     char *str = NULL,c,*res = NULL;
      13     int n,i,j,t;
      14     scanf("%d",&n);
      15     str = malloc(sizeof(char)*n);
      16     res = malloc(sizeof(char)*n);
      17     for(i = 0; i < n; i++)
      18     {
      19         getchar();
      20         scanf("%c",&c);
      21         str[i] = c;
      22     }
      23 
      24     i = 0;  //头部索引
      25     j = n-1; //尾部索引
      26     t = 0;
      27     while(i <= j)  
      28     {
      29         if(str[i] < str[j])
      30             res[t++] = str[i++];
      31         else if(str[i] > str[j])
      32             res[t++] = str[j--];
      33         else if(str[i] == str[j])  // 分析两者相等的情况
      34         {
      35             int left = i,right = j;
      36             while(str[left] == str[right] && left < right)  //如果下一位继续相等继续比较下一位
      37             {
      38                 left++;
      39                 right--;
      40             }
      41             if(str[left] < str[right] || left >= right)   //如果头部的值小或者比较到两者的索引相等(奇数个对称)和出现偶数个对称的情况,前后均可,次处选择前面的
      42             {
      43                 res[t++] = str[i++];
      44 
      45             }
      46 
      47             else if(str[left] > str[right])   //右边的小取右边
      48             {
      49                 res[t++] = str[j--];
      50             }
      51 
      52     return 0;
      53     }
  • 相关阅读:
    oracle 的exists 的用法
    linux
    C++纯虚函数
    C++ 的虚析构函数
    C++ new
    C++点和箭头操作符用法区别
    static
    关于C的int
    互斥量mutex的简单使用
    nginx服务器屏蔽上游错误码
  • 原文地址:https://www.cnblogs.com/programmer-cjr/p/3718062.html
Copyright © 2011-2022 走看看