首页 > 其他 > 详细

Codeforces Round #290 (Div. 2)

时间:2015-02-03 17:22:25      阅读:287      评论:0      收藏:0      [点我收藏+]

A.

http://codeforces.com/problemset/problem/510/A

签到题,画图形:

#include <iostream>
#include <stdio.h>
#include <algorithm>
#include <string.h>
#include <stdlib.h>
#include <cmath>
#include <iomanip>
#include <vector>
#include <set>
#include <map>
#include <stack>
#include <queue>
#include <cctype>
#define rd(x) scanf("%d",&x)
#define rd2(x,y)  scanf("%d%d",&x,&y)
#define rd3(x,y,z) scanf("%d%d%d",&x,&y,&z)
using namespace std;
typedef long long ll;
const int inf=0x3f3f3f3f;
int dx[8]={0,0,-1,1,1,1,-1,-1};
int dy[8]={1,-1,0,0,-1,1,-1,1};
int  n,m;

void draw1()
{
    for(int i=1;i<=m;i++)
        cout<<"#";
    cout<<endl;
}

void draw2()
{
    for(int i=1;i<=m-1;i++)
        cout<<".";
    cout<<"#"<<endl;
}

void draw3()
{
    cout<<"#";
    for(int i=1;i<=m-1;i++)
        cout<<".";
    cout<<endl;
}

int main()
{
    while(rd2(n,m)!=EOF)
    {
        for(int i=1;i<=n/2+1;i++)
        {
            draw1();
            if(i==n/2+1)
                break;
            if(i&1)
                draw2();
            else
                draw3();
        }
    }
    return 0;
}

B.

http://codeforces.com/problemset/problem/510/B

给定由26个大写字母组成的n*m的矩阵,问能不能找到环(相邻的相同字母连起来看能否找到一个环,相同字母的个数>=4,环最小是一个正方形)

DFS搜索,一开始想的是用DFs搜索,搜索到已经访问过的节点时,就结束,说明找到了,但存在一个问题,就是 1—>2->1这种情况,那无论如何都可以找到已经访问的节点,但这种情况个数只有2,不符合题意为。后来用step[x][y]表示第一次到达某点走的步数(第一个点为第一步),那么判断当第二次再到达该点时的步数 s,判断是否s-step+1>=4,如果可以,说明有环。

#include <iostream>
#include <stdio.h>
#include <algorithm>
#include <string.h>
#include <stdlib.h>
#include <cmath>
#include <iomanip>
#include <vector>
#include <set>
#include <map>
#include <stack>
#include <queue>
#include <cctype>
#define rd(x) scanf("%d",&x)
#define rd2(x,y)  scanf("%d%d",&x,&y)
#define rd3(x,y,z) scanf("%d%d%d",&x,&y,&z)
using namespace std;
typedef long long ll;
const int inf=0x3f3f3f3f;
int dx[8]={0,0,-1,1,1,1,-1,-1};
int dy[8]={1,-1,0,0,-1,1,-1,1};
int  n,m;
bool ok;
char mp[60][60];
bool vis[60][60];
int step[60][60];
int sx,sy;
int hash[30];

void DFS(int x,int y,int cnt)
{
    for(int i=0;i<4;i++)
    {
        int nx=x+dx[i];
        int ny=y+dy[i];
         if(vis[x][y]&&cnt-step[x][y]+1>=4)
       {
           ok=1;
           break;
       }
       // cout<<"sss"<<nx<<" "<<ny<<" "<<cnt<<endl;
        if(nx==sx&&ny==sy&&cnt>=4)
        {
            ok=1;
            break;
        }
        if(nx>=1&&nx<=n&&ny>=1&&ny<=m&&!vis[nx][ny]&&mp[nx][ny]==mp[x][y])
        {
            vis[nx][ny]=1;
            step[nx][ny]=step[x][y]+1;
            DFS(nx,ny,cnt+1);
            if(ok)
                return;
            step[nx][ny]=step[x][y]-1;
            vis[nx][ny]=0;
        }
    }
}

int main()
{
    while(rd2(n,m)!=EOF)
    {
        ok=0;
        memset(hash,0,sizeof(hash));
        for(int i=1;i<=n;i++)
            for(int j=1;j<=m;j++)
            {
                cin>>mp[i][j];
                hash[mp[i][j]-'A']++;
            }
        for(int i=1;i<=n;i++)
            for(int j=1;j<=m;j++)
        {
            if(hash[mp[i][j]-'A']>=4)
            {


               // bfs(i,j);
               sx=i,sy=j;
               memset(vis,0,sizeof(vis));
               step[sx][sy]=1;
               vis[sx][sy]=1;
               DFS(i,j,1);
            }
           if(ok)
                break;
        }
        if(ok)
            cout<<"Yes"<<endl;
        else
            cout<<"No"<<endl;
    }
    return 0;
}

后来看别人的代码,上面说到的问题,可以记录下前驱位置来解决, 比如 x,y的前驱位置是prex,prey , 那么对x,y进行扩展时,nx=x+dx[i],ny=y+dy[i],判断一下是否nx==prex&&ny==prey,如果成立,那么continue就可以了. 这样就解决了上述问题.

#include <iostream>
#include <stdio.h>
#include <algorithm>
#include <string.h>
#include <stdlib.h>
#include <cmath>
#include <iomanip>
#include <vector>
#include <set>
#include <map>
#include <stack>
#include <queue>
#include <cctype>
using namespace std;
int n,m;
char mp[52][52];
bool vis[55][55];
int dx[4]={0,0,-1,1};
int dy[4]={-1,1,0,0};
bool ok;


void DFS(int x,int y,int prex,int prey)
{
    vis[x][y]=1;
    for(int i=0;i<4;i++)
    {
        int nx=x+dx[i];
        int ny=y+dy[i];
        if(nx==prex&&ny==prey)//不能回走,向右走一步,不能在向左走一步
            continue;
        if(nx>=1&&nx<=n&&ny>=1&&ny<=m&&mp[nx][ny]==mp[x][y])
        {
            if(vis[nx][ny])
            {
                ok=1;
                return;
            }
            DFS(nx,ny,x,y);
        }
    }
}

int main()
{
    while(cin>>n>>m)
    {
        for(int i=1;i<=n;i++)
            for(int j=1;j<=m;j++)
            cin>>mp[i][j];
        memset(vis,0,sizeof(vis));
        ok=0;
        for(int i=1;i<=n;i++)
            for(int j=1;j<=m;j++)
        {
            if(!vis[i][j])
                DFS(i,j,0,0);
            if(ok)
            {
                cout<<"Yes"<<endl;
                return 0;
            }
        }
        cout<<"No"<<endl;
    }
    return 0;
}

C.

http://codeforces.com/problemset/problem/510/C

一般的字典序是a,b,c,d,e,f.......z,给定n个字符串,判断是否能修改字典序的顺序来使得这n个字符串是按字典序排列的.如果可以,那么输出修改以后的字典序(26个字母),否则输出Impossible。

不好理解,拿样例说明.

3个字符串 

rivest

shamir

adleman

很明显,这三个字符串不是按字典序排列的,因为a在字典序中排在r和s的前面,那么我们就修改a的优先级,把其放在s的后面,那么新的26个小写字母的字典序就变为了

bcdefghijklmnopqrsatuvwxzy,正好是我们所要输出的.

输出impossible的情况:

1.后面的一个字符串是前面的前缀.

比如      abb  和 a  ,这样 Impossible。

2.所要改变的字母字典序有环。

比如     d     c      a      d ,那么要修改为 d的字典序在c前面,d->c ,   c->a  ,a->d  ,成环,不可以。

所以可以用拓扑排序来做。

#include <iostream>
#include <stdio.h>
#include <algorithm>
#include <string.h>
#include <stdlib.h>
#include <cmath>
#include <iomanip>
#include <vector>
#include <set>
#include <map>
#include <stack>
#include <queue>
#include <cctype>
#define rd(x) scanf("%d",&x)
#define rd2(x,y)  scanf("%d%d",&x,&y)
#define rd3(x,y,z) scanf("%d%d%d",&x,&y,&z)
using namespace std;
typedef long long ll;
const int inf=0x3f3f3f3f;
const int maxn=30;
int mp[maxn][maxn];//存图
int indegree[maxn];//保存每个点的入读
string str[103];
int n;
bool flag;//判断是否存在环,1表示无环,0表示有环
bool ok;
string ans;
void topo()
{
    ans="";
    memset(indegree,0,sizeof(indegree));
    memset(mp,0,sizeof(mp));
    flag=1;
    for(int i=1;i<=n;i++)
        cin>>str[i];
    char a,b;
    for(int i=2;i<=n;i++)
    {
        int len1=str[i-1].length();
        int len2=str[i].length();
        for(int k=0;k<len1&&k<len2;k++)
        {
            if(str[i-1][k]!=str[i][k])
            {
                a=str[i-1][k];
                b=str[i][k];
                break;
            }
            if(k<len1&&k==len2-1)
                flag=0;
        }
        if(!flag)
            return;
        if(!mp[a-'a'][b-'a'])
        {
            indegree[b-'a']++;
            mp[a-'a'][b-'a']=1;
        }
    }
    flag=1;
    int i,j;
    for(i=0;i<26;i++)//找n次
    {
        bool is=0;
        for(j=0;j<26;j++)//找入度为0的点
        {
            if(indegree[j]==0)
            {
                is=1;
                ans.push_back('a'+j);
                indegree[j]--;
                for(int k=0;k<26;k++)//与其相连的边
                    if(mp[j][k])
                    indegree[k]--;
                break;
            }
        }
        if(is==0)//该次查找找不到入度为0的点
        {
            flag=0;
            break;
        }
    }
}

int main()
{
    while(rd(n)!=EOF)
    {
        topo();
        if(!flag)
            cout<<"Impossible"<<endl;
        else
        {
            cout<<ans<<endl;
        }
    }
    return 0;
}


Codeforces Round #290 (Div. 2)

原文:http://blog.csdn.net/sr_19930829/article/details/43449917

(0)
(0)
   
举报
评论 一句话评论(0
关于我们 - 联系我们 - 留言反馈 - 联系我们:wmxa8@hotmail.com
© 2014 bubuko.com 版权所有
打开技术之扣,分享程序人生!