【A】水题,模拟即可。

【B】水题,判断给定的图是否有环存在?dfs记录当前位置和从哪个方向来的即可!

const int dir[4][2] = {{0,1},{0,-1},{-1,0},{1,0}};

char maze[55][55];
bool vis[55][55];
int n,m,ok;

void dfs(int x,int y,int px,int py)
{
    if(vis[x][y]){
        ok = 1;
        return ;
    }
    vis[x][y] = 1;
    for(int i = 0; i < 4; i++){
        int dx = x + dir[i][0];
        int dy = y + dir[i][1];
        if(dx < 0 || dx >= n || dy < 0 || dy >= m) continue;
        if(dx == px && dy == py) continue ;
        if(maze[dx][dy] == maze[x][y])
        {
            dfs(dx,dy,x,y);
        }
    }
}

int main()
{
    while(scanf("%d%d",&n,&m)!=EOF)
    {
        ok = 0;
        for(int i = 0; i < n; i++) scanf("%s",maze[i]);
        memset(vis, false, sizeof(vis));
        for(int i = 0; i < n; i++){
            for(int j = 0; j < m; j++){
                if(!vis[i][j]){
                    dfs(i,j,i,j);
                    if(ok) break;
                }
            }
            if(ok) break;
        }
        if(ok) puts("Yes");
        else puts("No");
    }
}

【C】要你确定26小写字母的排列顺序,使得给定的字符串是按照这个字母表,按照字典序从小到大。容易瞧出来,这实际上就是一个有向图的拓扑序。复杂度O(n)

const int maxn = 111;
int in[maxn],ans[maxn],n;
char s[maxn][maxn];
vector<int>g[maxn];
queue<int>q;

void topsort()
{
    memset(ans, 0, sizeof(ans));
    while(!q.empty()) q.pop();
    for(int i = 0; i < 26; i++){
        if(!in[i]) q.push(i);
    }
    int num = 0;
    while(!q.empty())
    {
        int u = q.front();
        q.pop();
        ans[num++] = u;
        for(int i = 0; i < g[u].size(); i++){
            int v = g[u][i];
            --in[v];
            if(!in[v]){
                q.push(v);
            }
        }
    }
    //cout<<num<<endl;
    if(num < 26)
    {
        puts("Impossible\n");
        return ;
    }
    for(int i = 0; i < num; i++) printf("%c", ans[i] + 'a');
    printf("\n");
}

int main()
{
    while(scanf("%d", &n)!=EOF){
        memset(in, 0, sizeof(in));
        for(int i = 1; i <= n; i++) g[i].clear();
        for(int i = 0; i < n; i++) scanf("%s",s[i]);
        bool ok = 0;
        for(int i = 1; i < n; i++)
        {
            int len1 = strlen(s[i-1]);
            int len2 = strlen(s[i]);
            int a = 0,b = 0;
            while(a < len1 && b < len2 && s[i-1][a] == s[i][b])
            {
                a++;
                b++;
            }
            if(b == len2 && a < len1)
            {
                ok = 1;
                break;
            }
            if(a == len1 && b <= len2) continue;
            in[s[i][b]-'a']++;
            g[s[i-1][a]-'a'].push_back(s[i][b]-'a');
        }
        if(ok)
        {
            puts("Impossible");
        }
        else
        {
            topsort();
        }
    }
}

【D】给了一列数,每个数有个价值,要你找到一些数使得这些数可以组成数轴上的所有数。实际上就是让这些数的最大公约数为1即可,然后找这些集合的最小值。map+dp思想就可以了。mp[i]公约数为i的最小价值,暴力去更新就可以了,复杂度O(n*n)。

const int maxn = 333;
LL l[maxn],c[maxn];
map<LL,LL>mp;
int n;

int main()
{
    while(scanf("%d",&n) != EOF)
    {
        mp.clear();
        for(int i = 1; i <= n; i++) scanf("%lld",&l[i]);
        for(int i = 1; i <= n; i++) scanf("%lld",&c[i]);
        mp[0] = 0;
        for(int i = 1; i <= n; i++){
            for(map<LL,LL>::iterator it = mp.begin(); it != mp.end(); it++){
                LL v = it->first;
                LL x = __gcd(v, l[i]);
                if(mp.find(x)!=mp.end()) mp[x] = min(mp[x], it->second + c[i]);
                else mp[x] = it->second + c[i];
            }
        }
        if(!mp[1]) printf("-1\n");
        else{
            printf("%lld\n",mp[1]);
        }
    }
}

【E】网络流,留坑。