zoukankan      html  css  js  c++  java
  • 牛客小白月赛22

    链接:https://ac.nowcoder.com/acm/contest/4462/C
    来源:牛客网

    时间限制:C/C++ 1秒,其他语言2秒
    空间限制:C/C++ 262144K,其他语言524288K
    64bit IO Format: %lld

    题目描述

    一列上有12个孔,这12个孔中有些孔被遮挡住了。
    假定我们用 '-' 来表示没被遮挡住的孔,用 'o' 来表示被遮挡住的孔。
    如果相邻的三个孔有两个孔被遮挡,并且被遮挡的两个孔相邻,就是 '-oo' 和 'oo-'。
    对于这样的三个孔,我们可以将中间的孔的遮挡物移开,代价是将一端的遮挡物移到另一端没有被遮挡的孔上面。
    对于一列给定的孔,你的任务是制定操作的顺序,使得最后剩余的被遮挡的孔的个数最少,并输出最后剩余的被遮挡的孔的个数。

    输入描述:

    第一行输入一个n,n≤105
    接下来n行,每行12个字符,代表孔的状态。

    输出描述:

    对于每行输入在一行中输出一个数字代表答案。

    输入

    5
    ---oo-------
    -o--o-oo----
    -o----ooo---
    oooooooooooo
    oooooooooo-o

    输出

    1
    2
    3
    12
    1

    DFS即可,可以将这个字符串看作是一个二进制串,把所有的情况先处理一下,然后对应询问直接输出即可。

    https://pasteme.cn/28187

    直接按题意DFS,感觉也能写

     1 #include <bits/stdc++.h>
     2 typedef long long LL;
     3 const int INF=0x3f3f3f3f;
     4 const double eps =1e-8;
     5 const int mod=1e9+7;
     6 const int maxn=1e5+10;
     7 using namespace std;
     8 
     9 string str;
    10 int ans;
    11 
    12 int DFS()
    13 {
    14     for(int i=0;i<10;i++)
    15     {
    16         if(str[i]=='-'&&str[i+1]=='o'&&str[i+2]=='o')
    17         {
    18             str[i]='o'; str[i+1]='-'; str[i+2]='-';
    19             DFS();
    20             str[i]='-'; str[i+1]='o'; str[i+2]='o';
    21         }
    22         if(str[i]=='o'&&str[i+1]=='o'&&str[i+2]=='-')
    23         {
    24             str[i]='-'; str[i+1]='-'; str[i+2]='o';
    25             DFS();
    26             str[i]='o'; str[i+1]='o'; str[i+2]='-';
    27         }
    28     }
    29     int num=0;
    30     for(int i=0;i<12;i++)
    31     {
    32         if(str[i]=='o') num++;
    33     }
    34     ans=min(ans,num);
    35 }
    36 
    37 int main()
    38 {
    39     #ifdef DEBUG
    40     freopen("sample.txt","r",stdin);
    41     #endif
    42     
    43     int T;
    44     cin>>T;
    45     while(T--)
    46     {
    47         ans=INF;
    48         cin>>str;
    49         DFS();
    50         cout<<ans<<'
    ';
    51     }
    52     
    53     return 0;
    54 }

    状态压缩

    原牛客题解:https://ac.nowcoder.com/acm/problem/blogs/202476

    一共12个孔,只有2^12=4096种情况,但是查询次数很多,我们可以考虑用二进制1和0表示‘o’和‘-’两种状态,进行状态压缩,用一个二进制数代表一种情况。然后再在记忆化搜索的过程中把已知情况的答案记录下来,方便下次直接用。

    搜索的时候就找 '-oo' 和 'oo-',注意到它们有共同点:中间是1,两边不相同。“将中间的孔的遮挡物移开,将一端的遮挡物移到另一端没有被遮挡的孔上面。”其实就是把中间的1变为0,再把两边互换,对于二进制数011和110,我们只要将它^111即异或7(1和0异或上0不变,异或1则可互换)

    附:运算符优先级

     1 #include <bits/stdc++.h>
     2 typedef long long LL;
     3 const int INF=0x3f3f3f3f;
     4 const double eps =1e-8;
     5 const int mod=1e9+7;
     6 const int maxn=1e5+10;
     7 using namespace std;
     8 
     9 int vis[1<<12]; //记忆化数组
    10 
    11 int DFS(int x)
    12 {
    13     if(vis[x] || x==0) return vis[x]; //如果这种状态已经搜过了直接返回答案
    14     int num=0; //状态中1的个数
    15     for(int i=0;i<12;i++)
    16         if(x>>i&1) num++;
    17     for(int i=0;i<10;i++) //枚举'-oo' 和 'oo-'的右端
    18     {
    19         if(x>>(i+1)&1  &&  x>>i&1 ^ x>>(i+2)&1) //如果中间是1,两边不相同(异或为1)。注意运算符优先级,这里由高到低分别是()、+、>>、&、^
    20             num=min(num,DFS(x^7<<i)); //进行操作继续搜索
    21     }
    22     return vis[x]=num; //记忆化
    23 }
    24 
    25 int main()
    26 {
    27     #ifdef DEBUG
    28     freopen("sample.txt","r",stdin);
    29     #endif
    30     
    31     int T;
    32     scanf("%d",&T);
    33     while(T--)
    34     {
    35         int x=0; vis[0]=0;
    36         char str[15];
    37         scanf("%s",str);
    38         for(int i=0;i<12;i++)
    39             x=(x<<1)+(str[i]=='o'? 1:0); //将状态压缩进二进制数x
    40         printf("%d
    ",DFS(x));
    41     }
    42     
    43     return 0;
    44 }

    -

  • 相关阅读:
    Codeforces 525C Om Nom and Candies 枚举 + 复杂度分析
    Codeforces 526B Om Nom and Dark Park 树形dp
    Codeforces 526A King of Thieves 枚举
    Regionals 2014 Asia
    Regionals 2014 Asia
    access数据库和sqlsever数据库sql语句的布尔值boolean的写法
    取消阴影行
    引用其他单元的2种方法
    选中阴影行
    全选
  • 原文地址:https://www.cnblogs.com/jiamian/p/12571970.html
Copyright © 2011-2022 走看看