zoukankan      html  css  js  c++  java
  • 《挑战程序设计竞赛》 一二章部分代码题解

    最近在看这本书,由于我在网上没有找到代码,特地把我的代码贴出来以供参考。由于是手敲,与书上的有所不同,如有错误欢迎指教。

    1.6.2 POJ 1852

    本题关键在于理解两只蚂蚁相遇后相当于交错而过继续前行。

     1 #include <cstdio>
     2 #include <iostream>
     3 //#include <algorithm>
     4 #define max(a,b) ((a)>(b)?(a):(b))
     5 #define min(a,b) ((a)<(b)?(a):(b))
     6 using namespace std;
     7 int main(void)
     8 {
     9     int num;
    10     int length, n;
    11     scanf("%d",&num);
    12     for(int i=0; i<num; i++)
    13   {
    14     scanf("%d%d",&length,&n);
    15     int ma=0, mi=0;
    16     int temp;
    17     for(int j=0; j<n; j++)
    18     {
    19       scanf("%d",&temp);
    20       mi = max(mi, min(temp, length-temp));
    21       ma = max(ma, max(temp, length-temp));
    22     }
    23     printf("%d %d
    ",mi, ma);
    24   }
    25     return 0;
    26 }

    2.1 搜索

    2.1.4 POJ 2386

    #include <cstdio>
    #include <iostream>
    #include <algorithm>
    #include <cstring>
    using namespace std;
    int vis[105][105];//记忆数组 
    char s[105][105];
    int sum;
    int n, m;
    void dfs(int x, int y)
    {
      if(vis[x][y]==1 || x<0 || x>=n || y<0 || y>=m || s[x][y]=='.')  return;
      vis[x][y] = 1;
      dfs(x-1, y-1);  dfs(x-1, y);  dfs(x-1, y+1);
      dfs(x, y-1);                  dfs(x, y+1);
      dfs(x+1, y-1);  dfs(x+1, y);  dfs(x+1, y+1);//向八个方向搜索 
    }
    int main(void)
    {
        //freopen("2386.in","r",stdin);
        scanf("%d%d",&n,&m);
        sum = 0;
        getchar();//吃掉'
    ' 
        for(int i=0; i<n; i++)
        for(int j=0; j<=m; j++)//多一个字符吃掉'
    ' 
        {
          scanf("%c",&s[i][j]);
        }
      for(int i=0; i<n; i++)
        for(int j=0; j<m; j++)
        {
          if(vis[i][j]==0 && s[i][j]=='W')//有未搜索过的积水点 
          {
            sum++;
            dfs(i, j);
          }
        }
      printf("%d
    ",sum);
        return 0;
    }

    2.1.5迷宫最短路径(bfs)

     1 #include <cstdio>
     2 #include <iostream>
     3 #include <algorithm>
     4 #include <cstring>
     5 #include <queue>
     6 using namespace std;
     7 #define INF 6666666
     8 typedef pair<int, int>  P;
     9 int n, m;
    10 char maze[105][105];
    11 int d[105][105];//起点到所有点的最少步数 
    12 int dx[4]={1,0,-1,0}, dy[4]={0,1,0,-1};
    13 int sx, sy, gx, gy;
    14 queue<P>  que;
    15 void bfs()
    16 {
    17   while(que.size())
    18   {
    19     P p = que.front(); que.pop();
    20     if(p.first==gx && p.second==gy)  break;//队列第一个是已经被计算出来的 
    21     for(int i=0; i<4; i++)
    22     {
    23       int nx = p.first + dx[i];
    24       int ny = p.second + dy[i];//四个方向走 
    25       if(nx>=0 && nx<n && ny>=0 && ny<m && maze[nx][ny]!='#' && d[nx][ny]==INF)
    26       {
    27         que.push(P(nx,ny));//如果可以走,则该点入队列 
    28         d[nx][ny] = d[p.first][p.second] + 1;//求得该点最短步数 
    29       }
    30     }
    31   }
    32 }
    33 int main(void)
    34 {
    35     //freopen("2-1-5.in","r",stdin);
    36     scanf("%d%d",&n,&m);
    37     for(int i=0; i<n; i++)
    38     for(int j=0; j<=m; j++)
    39     {
    40       scanf("%c",&maze[i][j]);
    41       d[i][j] = INF;
    42       if(maze[i][j] == 'S')   { sx = i; sy = j; }//起点 
    43       if(maze[i][j] == 'G')   { gx = i; gy = j; }//终点 
    44     }
    45   d[sx][sy] = 0;
    46   que.push(P(sx, sy));//起点入队列 
    47   bfs();
    48   printf("%d",d[gx][gy]);
    49     return 0;
    50 }//2015-08-03 

    2.2 贪心

    2.2.3字典序最小问题(POJ3617)

    本题关键在于利用正反串的比较来决定选择头字母还是尾字母,另外注意80字符换行。

    #include <cstdio>
    #include <iostream>
    #include <algorithm>
    #include <cstring>
    using namespace std;
    char s[2005], s0[2005], t[2005];
    int n, b=0, g=0, b0=0, g0=0, u=0;
    char c;
    bool jud(void)
    {
      for(int i=0; i<n; i++)
      {
        if(s[b+i]!=s0[b0+i]) return (s[b+i]<=s0[b0+i]);
      }
    }//用于比较正串和反串来求最优解 
    int main(void)
    {
        //freopen("3617.in","r",stdin);
        scanf("%d",&n);
        for(int i=0; i<n; 1)
      {
        c = getchar();
        if(c>='A' && c<='Z')
        {
          s[i++] = c;
        }
      }
      for(int i=0; i<n; i++)
      {
        s0[i] = s[n-1-i];
      }//s0为s的反串 
      g=g0=n-1;
      while(b <= g)
      {
        if(jud()==1)  {t[u++]=s[b++];  g0--;}//取第一个字母 
        else  {t[u++]=s[g];    g--;  b0++;}//取最后一个字母 
      }
      for(int i=0; i<n; i++)
      {
          putchar(t[i]);
          if((i+1)%80 == 0)        putchar('
    ');
      }    //输出每80字符换行 
      if((n+1)%80 != 0)
          putchar('
    ');
        return 0;
    }//2015-08-03 

     2.2.4

    1. POJ 3069

    本题关键在于找到一个点r范围内的最后一个点和那个点r范围外的第一个点。

    #include <cstdio>
    #include <iostream>
    #include <algorithm>
    #include <cstring>
    using namespace std;
    int a[1005];
    int n, r;
    int main(void)
    {
        //freopen("3069.in","r",stdin);
        while(scanf("%d%d",&r,&n))
      {
        int sum=0;
        if(n==-1 && r==-1)
          return 0;
        for(int i=0; i<n; i++)
        {
          scanf("%d",&a[i]);//输入每个点的位置 
        }
        sort(a, a+n);
        int i=0;
        while(i < n)
        {
          int s = a[i++];//从s点开始 
          while(i<n && a[i]<=s+r)  i++;
          int p = a[i-1];        //找到起始点s区间r内最后一个点 p 
          while(i<n && a[i]<=p+r)  i++;//寻找下一个起始点 
          sum++;
        }
        printf("%d
    ",sum);
      }
        return 0;
    }//2015-08-03 

    2. POJ 3253

    通过每次连接最短的两块板可以解决。

    #include <cstdio>
    #include <iostream>
    #include <algorithm>
    #include <cstring>
    #include <cmath>
    using namespace std;
    int a[20005];
    int main(void)
    {
        //freopen("3253.in","r",stdin);
        int n;
        scanf("%d",&n);
        for(int i=0; i<n; i++)
      {
        scanf("%d",&a[i]);
      }
      long long res=0, t=0;
      while(n > 1)
      {
          int t1=0, t2=1;
          if(a[t1]>a[t2])    swap(t1,t2);
          for(int i=2; i<n; i++)
          {
              if(a[i]<a[t1])    swap(a[i], a[t1]);
              if(a[i]<a[t2])    swap(a[i], a[t2]);
          }    //找出最短板和次短板 
          t = a[t1]+a[t2];
          res+=t;
          a[t1]+=a[t2];
          if(t2!=n-1)        swap(a[t2], a[n-1]);
          n--;//将两块板连接 ,重复此步骤就可解决 
      }
      printf("%lld",res);
        return 0;
    }//2015-08-04 

     练习题

    2.1

    POJ 1979

    这道题还是比较简单的,主要要解决掉scanf最后的换行。

     1 #include <cstdio>
     2 #include <iostream>
     3 #include <algorithm>
     4 #include <cstring>
     5 using namespace std;
     6 int vis[25][25];
     7 char s[25][25];
     8 int n, m, cou;//行数,列数,结果 
     9 void dfs(int x, int y)
    10 {
    11     //如果走出矩阵则返回 
    12   if(x<0 || x>=m || y<0 || y>=n || s[x][y]=='#')  return;
    13   if(vis[x][y]==1)  return;
    14   vis[x][y] = 1;
    15   if(s[x][y] == '.' || s[x][y] == '@')
    16     cou++;
    17   //四个方向搜索  
    18           dfs(x, y-1);
    19   dfs(x-1, y);      dfs(x+1, y);
    20           dfs(x, y+1);
    21 
    22 }
    23 int main(void)
    24 {
    25   int x, y;
    26     //freopen("1979.in","r",stdin);
    27     while(scanf("%d%d",&n,&m))
    28   {
    29     if(n==0 && m==0)  return 0;
    30     getchar();    //吞掉多余的换行 
    31     //标记数组清零 
    32     memset(vis, 0, sizeof(vis));
    33     cou = 0;
    34     for(int i=0; i<m; i++)
    35     {
    36       for(int j=0; j<=n; j++)
    37       {
    38         scanf("%c",&s[i][j]);
    39         if(s[i][j]=='@')
    40         {
    41           x = i;
    42           y = j;
    43         }
    44       }
    45     }
    46     dfs(x, y);//从起点开始dfs 
    47     printf("%d
    ",cou);
    48   }
    49     return 0;
    50 }

     POJ 3009

    石头撞击墙壁后石头停下,墙壁破裂,还是暴力深搜,先判断能否直接到达终点,在搜索所有可行的走法。

      1 #include <cstdio>
      2 #include <iostream>
      3 #include <algorithm>
      4 #include <cstring>
      5 using namespace std;
      6 int s[25][25];
      7 int result;
      8 int sx, sy;
      9 int n, m;
     10 void dfs(int x, int y, int step, int type)
     11 {
     12   if(step > 10)   return;    //超过10步失败 
     13   //到达目的地    
     14   if(s[x][y] == 3)
     15   {
     16     if(result == -1)  result = step;
     17     else  result = min(result, step);
     18     return;
     19   }
     20   //石头把墙撞碎 
     21   switch(type)
     22   {
     23       case 1:  s[x-1][y] = 0;  break; //north
     24     case 2:  s[x+1][y] = 0;  break; //south
     25     case 3:  s[x][y-1] = 0;  break;  //west
     26     case 4:  s[x][y+1] = 0;  break;  //east
     27   }
     28   //四处搜索寻找终点        
     29   for(int i=1; i<=x; i++)
     30   {   
     31       if(s[x-i][y]==1)    break;
     32       if(s[x-i][y]==3)  
     33         {
     34             dfs(x-i, y, step+1, 0);
     35             break;
     36         }
     37   }
     38   for(int i=1; i<m-x; i++)
     39   {
     40     if(s[x+i][y]==1)    break;
     41     if(s[x+i][y]==3)  
     42     {
     43         dfs(x+i, y, step+1, 0);
     44         break;
     45     }
     46   }              
     47   for(int i=1; i<=y; i++)
     48   {
     49       if(s[x][y-i]==1)    break;
     50     if(s[x][y-i]==3)  
     51     {
     52         dfs(x, y-i, step+1, 0);
     53         break;
     54     }
     55   }
     56   for(int i=1; i<n-y; i++)
     57   {
     58       if(s[x][y+i]==1)    break;
     59     if(s[x][y+i]==3) 
     60     {
     61         dfs(x, y+i, step+1, 0);
     62         break;
     63     }
     64   } 
     65   //四处探索 
     66   if(x>=1 && s[x-1][y]!=1)
     67         for(int i=2; i<=x; i++)
     68             if(s[x-i][y]==1)  
     69             {
     70                 dfs(x-i+1, y, step+1, 1);
     71                 break;
     72             }
     73   if(x+1<m && s[x+1][y]!=1)
     74       for(int i=2; i<m-x; i++)
     75           if(s[x+i][y]==1)  
     76             {
     77                 dfs(x+i-1, y, step+1, 2);
     78                 break;
     79             }    
     80   if(y>=1 && s[x][y-1]!=1)
     81         for(int i=2; i<=y; i++)
     82         if(s[x][y-i]==1)  
     83             {
     84                 dfs(x, y-i+1, step+1, 3);
     85                 break;
     86             }
     87     if(y+1<n && s[x][y+1]!=1)
     88         for(int i=2; i<n-y; i++)
     89         if(s[x][y+i]==1)  
     90             {
     91                 dfs(x, y+i-1, step+1, 4);    
     92                 break;
     93             }                                
     94   //墙壁复原 
     95   switch(type)
     96   {    
     97         case 1:  s[x-1][y] = 1;  break;
     98     case 2:  s[x+1][y] = 1;  break;
     99     case 3:  s[x][y-1] = 1;  break;
    100     case 4:  s[x][y+1] = 1;  break;
    101   }
    102 }
    103 int main(void)
    104 {
    105     //freopen("3009.in","r",stdin);
    106     while(scanf("%d%d",&n,&m))  //m行n列
    107   {
    108     if(n==0 && m==0)  return 0;
    109     result = -1;
    110     for(int i=0; i<m; i++)
    111       for(int j=0; j<n; j++)
    112       {
    113         scanf("%d",&s[i][j]);
    114         if(s[i][j]==2) {sx=i; sy=j;}
    115       }
    116     dfs(sx, sy, 0, 0);
    117     printf("%d
    ",result);
    118   }
    119     return 0;
    120 }
  • 相关阅读:
    投票协议:二进制表示方法
    投票协议:构建和解析协议消息
    多任务处理:多线程
    通信:成帧与解析
    通信:组合输入输出流
    跨越FSO WSH写文件
    MS07004漏洞
    解决ASP(图像)上传漏洞的方法
    让硬件入侵不再是神话
    解决ASP(图像)上传漏洞的方法
  • 原文地址:https://www.cnblogs.com/mycd/p/4702766.html
Copyright © 2011-2022 走看看