zoukankan      html  css  js  c++  java
  • 2013 蓝桥杯B组C++

    剪格子 https://www.dotcpp.com/oj/problem1432.html

    解题思路:dfs从左上角向四个方向搜索,用bool数组判断保证在一次搜索中不重复遇到同一顶点。

    注意:输入是先列后行

    实现代码:

     1 #include<cstdio>
     2 #include<algorithm>
     3 using namespace std;
     4 
     5 const int INF = 1e9;
     6 const int Max_N = 10;
     7 
     8 int n,m;
     9 int number[Max_N][Max_N];
    10 bool visited[Max_N][Max_N];
    11 int sum;
    12 int res = INF;
    13 
    14 void dfs(int x, int y, int num, int cnt);
    15 
    16 int main()
    17 {
    18     scanf("%d%d",&m,&n);
    19     for( int i=0; i<n; i++ )
    20     {
    21         for( int j=0; j<m; j++ )
    22         {
    23             scanf("%d",&number[i][j]);
    24             sum += number[i][j]; 
    25         }
    26     }
    27     
    28     dfs(0,0,0,0);
    29     if( res==INF )    printf("0
    ");
    30     else            printf("%d
    ",res);
    31     
    32     return 0;
    33 }
    34 
    35 void dfs(int x, int y, int num, int cnt)
    36 {
    37     if( x<0 || x>=n || y<0 || y>=m || num>sum/2 || cnt>=res || visited[x][y] )
    38         return;
    39     
    40     visited[x][y] = true;
    41     num += number[x][y];
    42     cnt++;
    43     
    44     if( num==sum/2 )
    45     {
    46         res = min( res, cnt );
    47     }
    48     
    49     dfs(x+1,y,num,cnt);
    50     dfs(x-1,y,num,cnt);
    51     dfs(x,y+1,num,cnt);
    52     dfs(x,y-1,num,cnt);
    53     
    54     visited[x][y] = false;
    55 }
    View Code

    翻硬币  https://www.dotcpp.com/oj/problem1453.html

    解题思路:开关问题

      1.硬币区间翻转的顺序对结果无影响

      2.同一个区间([i,i+1])重复翻是多余操作

      所以我们规定从左到右判断,若不同则必须翻转,再此之后该位置就不需要考虑,问题规模-1。

    实现代码:

     1 #include<algorithm>
     2 #include<iostream>
     3 #include<string> 
     4 using namespace std;
     5 
     6 void clip(string &s, int i)
     7 {
     8     if( s[i]=='*' )    s[i] = 'o';
     9     else            s[i] = '*';
    10 }
    11 
    12 int main()
    13 {
    14     string s1,s2;
    15     cin>>s1>>s2;
    16     
    17     int res = 0;
    18     for( int i=0; i<s1.length()-1; i++ )
    19     {
    20         if( s1[i]!=s2[i] )
    21         {
    22             clip(s1,i);
    23             clip(s1,i+1);
    24             res++;
    25         }
    26     }
    27     cout<<res<<endl;
    28     
    29     return 0;
    30 }
    View Code

    连号区间数  https://www.dotcpp.com/oj/problem1456.html

    解题思路:解题的关键是连号区间数的判断--区间最大值与最小值之差是否等于区间长度。

    实现代码:

     1 #include<cstdio>
     2 #include<algorithm>
     3 using namespace std;
     4 
     5 const int Max_N = 5000;
     6 
     7 int N;
     8 int p[Max_N];
     9 
    10 int main()
    11 {
    12     scanf("%d",&N);
    13     for( int i=0; i<N; i++ )    scanf("%d",&p[i]);
    14     
    15     int res = N; //区间长度为1 
    16     for( int i=0; i<N-1; i++ )
    17     {
    18         int min_p = p[i], max_p = p[i];  //区间[i,j]的两个极值 
    19         for( int j=i+1; j<N; j++ )
    20         {
    21             min_p = min( min_p, p[j] );
    22             max_p = max( max_p, p[j] );
    23             if( (max_p-min_p) == (j-i) )    res++; //满足条件 
    24         }
    25     }
    26     printf("%d
    ",res);
    27     
    28     return 0;
    29 }
    View Code

    幸运数  https://www.dotcpp.com/oj/problem1441.html

    解题思路:暴力求解,简化之处:用step记录从1开始没被删除数字的个数,若step%cur(当前幸运数)则删除当前遍历的数字。

    实现代码

     1 #include<cstdio>
     2 #include<cstring>
     3 
     4 const int Max_N = 1000000;
     5 
     6 int m,n;
     7 bool dp[Max_N+1]; //dp[i] = false表示i被删除 
     8 
     9 int main()
    10 {
    11     int m,n;
    12     scanf("%d%d",&m,&n);
    13     
    14     memset(dp,true,sizeof(dp));
    15     int cur = 2;
    16     while( cur<=n )
    17     {
    18         int step = 0;
    19         for( int i=1; i<=n; i++ )
    20         {
    21             if( dp[i]==true )
    22             {
    23                 step++;
    24                 if( step%cur==0 )
    25                 {
    26                     dp[i] = false;
    27                 }
    28             }
    29         }
    30         cur++;
    31         while( !dp[cur] ) cur++; 
    32     }
    33     
    34     int res = 0;
    35     for( int i=m+1; i<n; i++ )
    36     {
    37         if( dp[i] )    res++;
    38     }
    39     printf("%d
    ",res);
    40     
    41     return 0;
    42 }
    View Code

    高僧斗法  https://www.dotcpp.com/oj/problem1459.html

    解题思路:解题Nim博弈问题,Nim博弈问题:参考  https://www.cnblogs.com/jiangjun/archive/2012/11/01/2749937.html

      Nim博弈问题说的是有几堆石子堆,两人轮流在任意石堆拿大于1个石子,最后拿光者得胜。博弈问题的结论是将所有石子堆数目异或,若为0则先手负,否则先手胜。

    对于先手负的一方即使尽量想破坏局势,先手胜的一方只要每次都在取后保证局面仍然是胜局势即可.

      应用于本题:

      将小和尚两两配对,如{a1, a2, a3, a4 } 将(a1,a2)与(a3,a4)配对,其间隔看作可以取的石子,最后取完者胜。我的理解是对于必胜的策略其先后对结果无影响,那么可以先将处于高台阶的a3取到最上面,之后

    取a1,a2,此时a2向上多少a1也可向上多少,a2与a3之间的间隔对结果无影响。(还不是特别清晰)

      对每个石子堆的数目遍历,直到与其他石子堆异或的结果异或为0.

      注意:每个石子堆数目既可以增加也可以减少!

    实现代码:

     1 #include<cstdio>
     2 
     3 const int Max_N = 100;
     4 
     5 int a[Max_N];
     6 int num[Max_N];
     7 
     8 int main()
     9 {
    10     int index = 0; 
    11     while( scanf("%d",&a[index])!=EOF )
    12         index++;
    13     
    14     int xor_ = 0; 
    15     for( int i=0; i<index-1; i+=2 )
    16     {
    17         num[i/2] = a[i+1] - a[i] - 1; //石子堆 两两配对 
    18         xor_ ^= num[i/2]; //所有石子堆异或结果 
    19     }
    20     
    21     if( xor_==0 ) //必败 
    22     {
    23         printf("%d
    ",-1);
    24     }
    25     else
    26     {
    27         bool flag = false;
    28         for( int i=0; i<index-1; i++ )
    29         {
    30             int x = num[i/2]^xor_;//a^b^a = b x为除该堆外其他堆异或结果 
    31             for( int k=a[i]+1; k<a[i+1]; k++ )
    32             {
    33                 /* 两个堆之间的num[i]可以增大/减小 */
    34                 /* 若a增大 b-a减小  若b增大 b-a增大 */
    35                 if( i%2==0 && ((a[i+1]-k-1)^x)==0 )
    36                 {
    37                     printf("%d %d
    ",a[i], k );
    38                     flag = true;
    39                     break;
    40                 }
    41                 else if( i%2==1 && ((k-a[i-1]-1)^x)==0 )
    42                 {
    43                     printf("%d %d
    ", a[i], k );
    44                     flag = true;
    45                     break;
    46                 }
    47             }
    48         
    49             
    50             if( flag )    break;
    51         }
    52     }
    53     
    54     return 0;
    55 }
    View Code

      

  • 相关阅读:
    常用正则搜集(已验证)
    oracle 如何跨用户查询数据
    SVN状态图标消失的解决方法
    oracle 简单列操作
    正则替换行尾,行末内容
    怎么解决svn清理失败且路径显示乱码问题
    Oracle坑爹入门踩坑篇
    如何过滤datable?
    JS产生模态窗口,关闭后刷新父窗体。(兼容各浏览器)
    6 Jmeter脚本组成和组件搭配
  • 原文地址:https://www.cnblogs.com/w-like-code/p/14504768.html
Copyright © 2011-2022 走看看