• codeforces 495C. Treasure 解题报告


    题目链接:http://codeforces.com/problemset/problem/495/C

    题目意思:给出一串只有三种字符( ')','(' 和 '#')组成的字符串,每个位置的这个字符 '#'可以替换成不少于 1 个的 ')',问如何对每个'#'进行替换,使得对于字符串的任意一个位置, ')' 的数量始终不大于'(' 的数量。注意,'#'被替换成')'的总数以及原先有的')'的数量之和 == '(' 的总数。

      花了两个晚上的一点时间,今天在图书馆里终于想到解决方案了,大感动 ~~~~ >__<

        /********************************************* (错误思路请忽略= =)

      第一个晚上做的时候,只知道最好的填法就是,除了最后一个'#'之外,其他都替换为一个 ')',最后一个就根据公式: 数量 '(' -  数量 ')' - (总的'#'数 - 1)  来填入。

      但是问题是,如何确定有解。我当时很天真地以为,如果 '(' == ')' 但是'#'还有剩('#' > 0)就无解,test7:#)))) 证明此想法是错的,本来答案是-1,我程序输出 -4,因为这个判断是有缺陷的,排除不了这种情况。后来干脆直接保存每个位置的'(' (cnt[]) 和  ')'(cnt1[])的数量还有 '#'的数量,如果是'(',cnt[i] = cnt[i-1]+1,cnt1[i] = cnt[i-1];如果是')',cnt1[i] = cnt1[i-1]+1,cnt[i] = cnt[i-1];如果是'#',cnt[i] = cnt[i-1],cnt1[i] = cnt1[i-1]。'(', ')', '#'总数量分别对应c1, c2, c0,然后加多一个check()函数来判断如果cnt[i] < cnt1[i] 就 返回false,我只能说:有点不知所谓 = =....因为压根就没有考虑'#' 的值!不知道'#'具体填什么【test12 ##((((((() 】。改改改接着就是test14........噩梦啊~~~~煎熬啊

      **********************************************/

      早上重新想过,终于有头绪了。我的做法应该叫做所谓的反证法吧~~~~容易知道最保守最可行的方法就是:除了最后一个'#'之外的所有 '#' 都替换为 一个')'。

      设两个整型数tot 和c(初始值都为 0, c 用来保存'#'的数量),一个数组vis[],保存每个'#'的位置的替换个数,遍历一遍数组s[i]

      if 【'('】 tot++

      if 【')'】 tot--

      if 【'#'】 c++, vis[i] = 1 

      然后反向遍历数组s[i],找出最后一个'#'的位置,使得vis[i] = tot - (c-1)。但是前期要做一个判断工作,tot-(c-1) <= 0是无解的!,它专门处理 '(' == ')',c >= 1 的情况(类似(#),或者 #)。

      最后当然就是判断无解情况啦。开一个整数 cnt = 0,从前往后遍历数组s[],

      if 【'('】 cnt++

      if 【')'】 cnt--

      if 【'#'】 cnt -= vis[i]

      需要检查每个位置的cnt的值,if (cnt < 0) 就返回false。即表示 ) > ( ,不满足题目要求。

      最后返回true的情况是 cnt == 0,这样才能保证    '#' 替换为 ')' 以及本来存在的 ')' 的数量之和 等于 ‘(' 的数量

      如果经得起 check() 函数的考验,那么就输出解。

        

     1 #include <iostream>
     2 #include <cstdio>
     3 #include <cstdlib>
     4 #include <cstring>
     5 using namespace std;
     6 
     7 const int maxn = 1e5 + 5;
     8 char s[maxn];
     9 int vis[maxn], len;
    10 
    11 bool check(char s[])
    12 {
    13     int cnt = 0;
    14     for (int i = 0; i < len; i++)
    15     {
    16         if (s[i] == '(')
    17             cnt++;
    18         else if (s[i] == ')')
    19             cnt--;
    20         else             // #
    21             cnt -= vis[i];
    22         if (cnt < 0)      // 任意位置都要保证 ')' <= '('
    23             return false;
    24     }
    25     if (cnt == 0)
    26         return true;
    27     return false;
    28 }
    29 
    30 int main()
    31 {
    32     #ifndef ONLINE_JUDGE
    33         freopen("in.txt", "r", stdin);
    34     #endif // ONLINE_JUDGE
    35 
    36     while (scanf("%s", s) != EOF)
    37     {
    38         memset(vis, 0, sizeof(vis));
    39 
    40         len = strlen(s);
    41         int tot = 0, c = 0;
    42         for (int i = 0; i < len; i++)
    43         {
    44             if (s[i] == '(')
    45                 tot++;
    46             else if (s[i] == ')')
    47                 tot--;
    48             else       // #
    49             {
    50                 c++;
    51                 vis[i] = 1;
    52             }
    53         }
    54         if (tot-(c-1) <= 0)
    55             printf("-1
    ");
    56         else
    57         {
    58             int last = tot - (c-1);   // 最后一个 # 的赋值,至少要为1
    59             for (int i = len-1; i >= 0; i--)
    60             {
    61                 if (s[i] == '#')
    62                 {
    63                     vis[i] = last;
    64                     break;
    65                 }
    66             }
    67             if (!check(s))
    68                 printf("-1
    ");
    69             else
    70             {
    71                 for (int i = 1; i <= c-1; i++)
    72                     printf("1
    ");
    73                 printf("%d
    ", last);
    74             }
    75         }
    76     }
    77     return 0;
    78 }
  • 相关阅读:
    AndroidStudio修改程序的包名,可以修改com.example.xxx之类的详解
    【Android】Android开发点击查看手机电量的小功能。学习广播的一个小技能小Demo
    linux系统工程师修改打开文件数限制代码教程。服务器运维技术
    修改linux操作系统的时间可以使用date指令 运维系统工程师必会技术
    MySQL常用指令,java,php程序员,数据库工程师必备。程序员小冰常用资料整理
    android开发之java代码中字符串对比忽略大小写。java程序员必回,可用来比对验证码等问题
    android开发之使edittext输入弹出数字软键盘。亲测可用。手机号登陆注册常用。
    java工具类去掉字符串String中的.点。android开发java程序员常用工具类
    JS——tab函数封装
    JS——样式类的添加
  • 原文地址:https://www.cnblogs.com/windysai/p/4175404.html
Copyright © 2020-2023  润新知