• CodeForces Round #283 Div.2


    A. Minimum Difficulty

    题意:

    有一个递增序列a,现在要去掉除了第一项和最后一项元素外的某一项,使新数列中相邻元素之差的最大值最小。

    分析:

    先求出原序列a中,相邻两项元素之差的最大值m。

    枚举去掉ai,则新序列相邻元素差的最大值为max{ m, ai+1 - ai },然后记录最小值即可。

     1 #include <cstdio>
     2 #include <algorithm>
     3 using namespace std;
     4 
     5 const int maxn = 100 + 10;
     6 int a[maxn];
     7 
     8 int main(void)
     9 {
    10     int n;
    11     scanf("%d", &n);
    12     for(int i = 0; i < n; ++i) scanf("%d", &a[i]);
    13     int max1 = 0;
    14     for(int i = 0; i < n-1; ++i) max1 = max(max1, a[i+1]-a[i]);
    15 
    16     int ans = 10000;
    17     for(int i = 1; i < n-1; ++i) ans =min(ans, max(max1, a[i+1]-a[i-1]));
    18 
    19     printf("%d
    ", ans);
    20 
    21     return 0;
    22 }
    代码君

    B. (贪心)Secret Combination

    题意:

    给出一个n(≤1000)位数字,有下面两种操作:

    1. 将每位数字都自增1,如果是9的话变为0.(注意,每个数位上的数字都是单独操作的互不影响,没有相互之间的进位)
    2. 将每位数字向右移一位,最右边的数字则移到最左边

    求经过若干次操作,n能变为的最小数字。

    分析:

    首先我们想一下,最小的数字会有什么特点?那就是他前面会有很多前导0

    可以把几个连续相同的数字通过操作1加上某个数使其全部变为0,然后通过操作2将其变为前导0

    比如:325556,可以进行5次操作1变为870001,然后进行4次操作2,变为000187.

    因此,可以预处理n,求出最长连续数字,如果对应有多个相同长度的连续数字,则记录下他们的长度和位置,方便在后面进行比较。

    还要注意的是:由于操作2的特性,要考虑到首尾相接也可能出现相同连续的数字,所以我们可以对数组的索引模n取余或者将数字适当延长两倍或三倍。

     1 #include <cstdio>
     2 #include <algorithm>
     3 #include <cstring>
     4 using namespace std;
     5 
     6 const int maxn = (1000 + 10)*3;
     7 char s[maxn], s1[maxn], s2[maxn];//输入的数字,当前最小数字,要比较的数字
     8 int n;
     9 
    10 struct Queue
    11 {
    12     int pos, len;
    13     Queue(int p=0, int l=0):pos(p), len(l) {}
    14 }q[maxn]; //记录下连续相同数字的其实位置和个数
    15 
    16 bool lessthan(char* a, char* b)
    17 {//比较数字a是否小于b
    18     int i = 0;
    19     while(i < n && a[i] == b[i]) i++;
    20     if(i >= n) return false;
    21     return a[i] < b[i];
    22 }
    23 
    24 int main()
    25 {
    26     scanf("%d", &n);
    27     scanf("%s", s);
    28     strcpy(s1, s);
    29     for(int i = 0; i < n; ++i) s[i+n] = s[i+2*n] = s[i];
    30     int lx = 1, p = 0;
    31     for(int i = 0; i < 2*n; i++)
    32     {
    33         int st = i;
    34         int temp = 1;
    35         while(i < 2*n-1 && s[i] == s[i+1])
    36         {
    37             temp++;
    38             i++;
    39         }
    40         q[p++] = Queue(st, i+1-st);
    41         if(temp > lx)
    42             lx = temp;  //记录最长相同数字
    43     }
    44 
    45     for(int i = 0; i < p; ++i)
    46     {
    47         if(q[i].len == lx)
    48         {
    49             int add = ('9' + 1 - s[q[i].pos]) % 10;//将这些相同数字加上add然后全部变为前导0
    50             for(int j = 0; j < n; ++j)
    51             {
    52                 s2[j] = '0' + (s[q[i].pos+j]-'0'+add)%10;
    53             }
    54             if(lessthan(s2, s1))
    55             {
    56                 for(int k = 0; k < n; ++k) s1[k] = s2[k];
    57             }
    58         }
    59     }
    60 
    61     for(int i = 0; i < n; ++i) printf("%c", s1[i]);
    62     printf("
    ");
    63 
    64     return 0;
    65 }
    代码君

    C. (字符串、贪心)Removing Columns

    题意:

    给出n×m(n,m≤100)的字符矩阵,求最少去掉多少列,使得剩下的字符串从上到下是按字典序费递减排列的。

    分析:

    单独看一列:如果某个字母比它下面的字母要大,那么这一列一定不能作为最终字符串开头的一列。

    从左往右扫,直到找到能作为最终字符串开头的一列c1为止。

    则c1一定要保留,作为字符串的开头,贪心的理由是:

    如果后面也有一列c2满足作为字符串的开头,则c1...c2...从上到下一定满足字典序的顺序,而且不会使去掉的列数变多。

    选好字符串开头以后,继续往后扫描:

    如果本来某一行的字符串小于下面的字符串,则后面无论接什么样的字符,这两个字符串大小关系不变。

    如果原来某一行字符串等于下面一行的字符串,则后面接的字符也要满足大小关系。

     1 #include <cstdio>
     2 
     3 const int maxn = 100 + 10;
     4 bool bad[maxn], equ[maxn];//equ标记当前字符串中相邻两行是否相等
     5 //bad标记该列是否被去掉,作为答案的统计
     6 
     7 char table[maxn][maxn];
     8 
     9 int main()
    10 {
    11     //freopen("in.txt", "r", stdin);
    12 
    13     int n, m;
    14     scanf("%d%d", &n, &m);
    15     for(int i = 0; i < n; ++i) scanf("%s", table[i]);
    16 
    17     if(n <= 1)
    18     {
    19         puts("0");
    20         return 0;
    21     }
    22 
    23     int st = 0;//找到字符串的开头
    24     for(; st < m; ++st)
    25     {
    26         int i;
    27         for(i = 0; i < n-1; ++i)
    28             if(table[i][st] > table[i+1][st])
    29                 break;
    30         if(i == n-1) break;
    31     }
    32     if(st == m)
    33     {
    34         printf("%d
    ", m);
    35         return 0;
    36     }
    37 
    38     int ans = st;
    39     for(int i = 0; i < n-1; ++i)
    40     {
    41         if(table[i][st] == table[i+1][st])
    42             equ[i] = true;
    43     }
    44     for(int i = st+1; i < m; ++i)
    45     {
    46         for(int j = 0; j < n-1; ++j)
    47         {
    48             if(equ[j] && table[j][i] > table[j+1][i])//只有原来字符串相等且后面接的字符不满足顺才去掉该列
    49                 bad[i] = true;
    50         }
    51         if(bad[i])
    52             ans++;//统计被去掉的行数
    53         else
    54         {
    55             for(int j = 0; j < n-1; ++j)
    56             {
    57                 if(equ[j] && table[j][i] < table[j+1][i])//更新equ
    58                     equ[j] = false;
    59             }
    60         }
    61     }
    62 
    63     printf("%d
    ", ans);
    64 
    65     return 0;
    66 }
    代码君
  • 相关阅读:
    kb,mb
    搜狗浏览器“Alt+Z”(重新打开刚关闭的页面)失效的解决方案——使用“hkexplr”查看占用的快捷键
    在 Windows server 中备份数据、分区、磁盘,以及硬盘对拷——傲梅轻松备份2.1.0汉化破解技术员版
    使用了阵列卡的服务器,在Windows系统内看到硬盘的品牌、型号信息——aida64
    利用“VeraCrypt”创建加密卷(文件夹加密,较高强度)
    Windows下多个硬盘显示为一个分区的方案
    win10企业版400年密钥
    Easy2Boot——可制作多包含多个原版系统(.iso)的工具
    第三方资源管理器——XYplorer(可自定义文件夹颜色)
    Windows10专业版(版本号:21H1)安装后的设置
  • 原文地址:https://www.cnblogs.com/AOQNRMGYXLMV/p/4170872.html
Copyright © 2020-2023  润新知