现在的位置: 首页 > 综合 > 正文

2013年3月24日 周赛 解题报告 — from lanshui_Yang

2019年01月08日 ⁄ 综合 ⁄ 共 2223字 ⁄ 字号 评论关闭

#include<iostream>
#include<cstdio>
#include<cmath>
#include<cstring>
#include<algorithm>
using namespace std;
int n ,m ;
char s[55][55] ;
int vis[55][55] ;
int X[4] = {0,0,1,-1} ;
int Y[4] = {1,-1,0,0} ;
int cango(int x, int y)
{
    if(x >= 0 && x < n && y >= 0 && y < m && s[x][y] == 'B')
    return 1 ;
    return 0 ;
}
void dfs(int x , int y , int cnt , int ben) // cnt是标志变量,具体应用如下,ben 是为了记录上一次的方向
{
    vis[x][y] = 1 ;
    int k ;
    for(k = 0 ; k < 4 ; k ++)
    {
        int tx , ty ;
        tx = x + X[k] ;
        ty = y + Y[k] ;
        int tben , tcnt ;
        if(cango(tx , ty))
        {
            if(cnt == 0) // cnt == 0 代表起点
            {
                ben = k ;
                tcnt = cnt + 1 ;
                tben = ben ;
                dfs(tx,ty,tcnt,tben) ;
            }
            else if(cnt == 1 && k != ben) // 此种情况是第一次改变方向
            {
                tben =  k ;
                tcnt = cnt + 1 ;
                dfs(tx,ty,tcnt,tben) ;
            }
            else if(cnt == 2 && k != ben) // 此种情况 是 第二次 改变方向
            {
                continue ;
            }
            else if(cnt == 1 && k == ben) // 此种情况是来到当前点的方向与上一次的方向相同,此前“还未改变过“方向
            {
                tben =  k ;
                tcnt = cnt ;
                dfs(tx,ty,tcnt,tben) ;
            }
            else if (cnt == 2 && k == ben) // 此种情况是来到当前点的方向与上一次的方向相同,此前“已经改变过一次”方向
            {
                tben =  k ;
                tcnt = cnt ;
                dfs(tx,ty,tcnt,tben) ;
            }
        }
    }
}
int main()
{
    while (scanf("%d%d",&n,&m) != EOF)
    {
        int i ;
        int j ;
        for(i  = 0 ; i < n ; i ++)
        {
            for(j = 0 ; j < m ; j ++)
            {
                cin >> s[i][j] ;
            }
        }
        int pan = 0 ;
        for(i = 0 ; i < n ; i ++)
        {
            for(j = 0 ; j < m ; j ++)
            {
                if(s[i][j] == 'B')
                {
                    memset(vis , 0 , sizeof(vis)) ;
                    dfs(i,j,0,-1) ;
                    int i2 , j2 ;
                    for(i2 = 0 ; i2 < n ; i2 ++)
                    {
                        for(j2 = 0 ; j2 < m ; j2 ++)
                        {
                            if(s[i2][j2] == 'B' && !vis[i2][j2])
                            {
                                pan = 1;
                                break ;
                            }
                        }
                        if(pan == 1)
                        break ;
                    }
                }
                if(pan == 1)
                break ;
            }
            if(pan == 1)
            break ;
        }
        if(pan == 1)
        printf("NO\n") ;
        else
        printf("YES\n") ;
    }
    return 0 ;
}

      这次周赛的A、F、H题都是比较水的题,不作详细讲解,C题是简单的并查集问题,也不再敖述,下面着重讲一讲B题和G题:

      B题 :

题目大意 : 给你几个字符串 ,让你找出这些字符串中都未出现过的字符串,将字典序最小的输出。

程序如下 :

#include<iostream>
#include<cstdio>
#include<string>
#include<cstring>
#include<queue>
#include<cstdlib>
#include<vector>
#include<algorithm>
using namespace std;
struct pp
{
    int x ;
    char s[35] ;
} p[35] ;
char zimu[30];  // 装 26 个 英文字母 
char A[35] ; // 定义源字符串数组
int n ;
int pan ;
int n2 ;
int res ; 
void dfs(int cur) // 用dfs来枚举子串
{
    if(res == 1)
    return ;
    int i;
    for(i = 0 ; i < 26 ; i ++)
    {
        A[cur] = zimu[i] ;
        pan = 0 ;
        if(cur == n2 - 1)
        {
            for(int j = 0 ; j < n ; j ++)
            {
                char *k ;
                k = strstr(p[j].s,A) ; // 在A中查找子串
                if(k)
                {
                    pan = 1 ;
                    break ;
                }
            }
        }
        if(cur == n2 - 1 && pan == 0)
        {
            cout << A << endl ;
            res = 1 ;
            return ;
        }
        else if(cur < n2 - 1)
        {
            dfs(cur + 1) ;
            A[cur] = '\0' ;
        }
    }
}
int main()
{
    int i ;
    for(i = 0; i < 26 ; i ++)
    {
        zimu[i] = 'a' + i ;
    }
    while (scanf("%d",&n) != EOF)
    {
        memset(A,'\0',sizeof(A)) ;
        for(i = 0 ; i < n ; i ++)
        {
            scanf("%s",p[i].s) ;
            p[i].x = 0 ;
        }
        res = 0 ;
        int i ;
        for(i = 1 ; i < 35 ; i ++)  // 根据子串的长度来枚举子串
        {
            if(!res)
            {
                n2 = i;
                dfs(0) ;
            }
            else
            {
                break ;
            }
        }
    }
    return 0 ;
}

  G题 :

题目大意: 给你一个 n * m 的网格,每个小格不是白色就是黑色,问:对网格中的任意两个黑色小格,设为X和Y,     X能不能通过其它黑色小网格到达Y(注意:途中只能改变一次方向) ?

        思路:这道题我使用DFS做的,这个程序不仅适用于只能改变一次方向,任意次方向均能解决。  

具体程序如下:


抱歉!评论已关闭.