• UVaLive 4868 Palindrometer (暴力 / 构造)


    题意:

    给定一个固定长度的字符串, 字符串是一个含有前导0的数字, 问这个数字加上多少能构成一个回文字符串。

    分析:

    其实这题有很多种方法, 方法12是我做完后看别人代码总结的, 方法3是我当时想的一种方法。

    方法一:

    最直观的想法,从这个数字开始枚举, 知道找到回文字符串为止。

    注意 %0'length‘d 可以输出前导0 , 比如 %03d输出1的话就是 ”001“

    另外代码需要注意效率, 不然容易超时。

     1 #include<bits/stdc++.h>
     2 using namespace std;
     3 int len;
     4 bool pre(const char a[]){//判断是否回文串
     5     for(int i = 0, j = len - 1; i < j; i++, j--){
     6         if(a[i] != a[j])
     7             return false;
     8     }
     9     return true;
    10 }
    11 int main(){
    12     char str[30];
    13     while(scanf("%s", str )){
    14         len = strlen(str);
    15 
    16         if (len == 1) break;
    17 
    18         int i = 0, n = atoi(str);//先将str转化为int
    19 
    20         char print[50], buf[50];
    21 
    22         sprintf(print, "%%0%dd", len);//构造出“%0'长度'd”的字符串, 方便下面sprintf输出前导0
    23 
    24         memcpy(buf,str,len);//可以将枚举数组设为buf, 就不用更改原来数组了
    25 
    26 
    27         while(!pre(buf)){//枚举即可
    28             i++;
    29             sprintf(buf,print, n + i);
    30         }
    31         printf("%d
    ", i);
    32 
    33     }
    34 }

    方法二:

    构造出最接近的回文串, 方法是从判断每一对回文, 如果高位大于低位, 低位更改为高位, 否则低位的前一位进一, 低位更改为高位。

     1 #include<bits/stdc++.h>
     2 using namespace std;
     3 int len;
     4 int a[20];
     5 char s[20];
     6 void carry(){
     7     for(int i = len - 1; i >= 0; i --){
     8         if(a[i] >= 10){
     9             a[i-1] ++;
    10             a[i] %= 10;
    11         }
    12     }
    13 }
    14 bool change(){
    15     for(int i = 0, j = len - 1; i < j; i++, j--){
    16         if(a[i] > a[j]){
    17             a[j] = a[i];//位置对应的高低位, 如果高位大于低位的, 后面直接更改为低位
    18         }else if(a[j] > a[i]){
    19             a[j] = a[i];//否则 如果低位大于高位的, 低位的前一位++, 低位改为高位
    20             a[j-1] ++;
    21             carry();
    22             return true;//进位后要重新进行一次change(), 因为进位的可能是之前已经判断过的字符
    23         }
    24     }
    25     return false;
    26 }
    27 int main(){
    28     while(scanf("%s", s)){
    29         len = strlen(s);
    30         if(len == 1) break;
    31         int n1, n2;
    32         sscanf(s,"%d", &n1);
    33         for(int i = 0; i < len; i++){
    34             a[i] = s[i] - '0';
    35         }
    36         a[len] = 0;
    37         while(change());
    38         n2 = 0;
    39         for(int i = len - 1; i >=0;i--){
    40             n2 *= 10;
    41             n2 += a[i];
    42         }
    43         printf("%d
    ", n2 - n1);
    44     }
    45     return 0;
    46 }

    方法三:

    我自己的想法是判断最内层的非回文对, 如果高位大于低位, 那么低位以及低位之后的都更改为高位的回文,

    否则的话, 偶数情况中间两个字符中较小的(同样大小取高位),奇数情况则直接取中间的数, 这个数字+1, 如果有进位先进位。

    然后这个数字之后的所有数字都更改为与之对应的高位, 那么就是回文串。

     1 #include <bits/stdc++.h>
     2 using namespace std;
     3 int n;
     4 int len;
     5 int main(){
     6     char s[20];
     7     while(scanf("%s", s)){
     8         int len = strlen(s);
     9         int n1, n2;
    10         sscanf(s,"%d",&n1);
    11 
    12         if (len == 1){
    13             break;
    14         }
    15         int k = -1, i;
    16 
    17         for(i = 0; i < len/2; i++){
    18             if(s[i] != s[len - i - 1]){
    19                 k = i;
    20             }
    21         }
    22         if(k == -1){
    23             printf("0
    ");
    24             continue;
    25         }
    26 //        printf("k : %d
    ", k);
    27         if( s[len - k - 1] < s[k]){//如果最里面不同一对的低位 小于高位 改这一对的后面
    28             s[len-k-1] = s[k];
    29             int cnt = 0;
    30             for(int i = len-k; i < len; i++){
    31                 s[i] = s[len - i - 1];
    32             }
    33         }
    34         else // 只能改中间
    35         {
    36             int mid;
    37             if(len % 2 == 0){//偶数情况哪个小要哪个
    38                 mid = s[len/2-1] <= s[len/2] ? len/2-1: len/2;
    39             }
    40             else{
    41                 mid = len/2;
    42             }
    43 
    44             s[mid]++;
    45             for(int i = mid; i >=0 ; i--){
    46                 if(s[i] > '9'){
    47                     s[i] = '0';
    48                     s[i-1]++;
    49                 }
    50             }
    51             for(int i = mid+1; i < len; i++){
    52                 s[i] = s[len-i-1];
    53             }
    54 
    55         }
    56         sscanf(s,"%d",&n2);
    57         printf("%d
    ", n2 - n1);
    58 
    59     }
    60     return 0;
    61 }
  • 相关阅读:
    进程 线程 协程
    TCP的滑动窗口和网络拥塞控制
    Golang中函数结构体,将函数转换为接口
    go的调度 与 go 的GC
    未来程序员这个工种会如何进化与“35岁之殇”的思考
    golang 实现 LRU
    golang 单例模式实现
    内存泄露及内存溢出,解决方案
    Jvm调优参数
    HttpUtil
  • 原文地址:https://www.cnblogs.com/Jadon97/p/7248561.html
Copyright © 2020-2023  润新知