zoukankan      html  css  js  c++  java
  • 1341 无序字母对

    难度:提高+/省选-

    题目类型:图论

    提交次数:6

    涉及知识:dfs/欧拉路径

    题目描述

    给定n个各不相同的无序字母对(区分大小写,无序即字母对中的两个字母可以位置颠倒)。请构造一个有n+1个字母的字符串使得每个字母对都在这个字符串中出现。

    输入输出格式

    输入格式:

    第一行输入一个正整数n。

    以下n行每行两个字母,表示这两个字母需要相邻。

    输出格式:

    输出满足要求的字符串。

    如果没有满足要求的字符串,请输出“No Solution”。

    如果有多种方案,请输出前面的字母的ASCII编码尽可能小的(字典序最小)的方案

    输入输出样例

    输入样例#1:
    4
    aZ
    tZ
    Xt
    aX
    输出样例#1:
    XaZtX
    

    说明

    【数据规模与约定】

    不同的无序字母对个数有限,n的规模可以通过计算得到。

    代码:

     1 #include<iostream>
     2 using namespace std;
     3 int n;
     4 const int N = 52;
     5 int map[60][60];
     6 int du[60];
     7 char ans[2500];
     8 bool flag;
     9 int change(char a){
    10     int askii = (int)(a);
    11     if(askii<97){
    12         return askii-65;
    13     }
    14     else return askii-71;
    15 }
    16 char rechange(int x){
    17     if(x<=25) return char(x+65);
    18     else return char(x+71);
    19 }
    20 void dfs(int x, int step){    
    21     ans[step] = rechange(x);
    22     if(step==n+1){
    23         flag = true;
    24         return;
    25     }
    26     for(int i = 0; i < 52; i++){
    27         if(map[x][i]>0){
    28             map[x][i]--;
    29             map[i][x]--;
    30             dfs(i,step+1);    
    31             if(flag) break;
    32             map[x][i]++;
    33             map[i][x]++;
    34         }
    35     }
    36     if(!flag) ans[step] = 0;
    37 }
    38 int main(){
    39     cin>>n;
    40     int i;
    41     for(i = 1; i <= n; i++){
    42         char a, b;
    43         cin>>a>>b;
    44         int x = change(a);
    45         int y = change(b);
    46         map[x][y] = 1;
    47         map[y][x] = 1;
    48         du[x]++;
    49         du[y]++;
    50     }
    51     int flag = 100;
    52     int minn = 100;
    53     int odd = 0;
    54     for(i = 0; i <= 51; i++){
    55         if(du[i]!=0&&minn==100) minn = i;
    56         if(du[i]%2 == 1){
    57             flag = min(flag, i);
    58             odd++;
    59         }
    60             
    61     }
    62     if(odd!=0&&odd!=2) {
    63         cout<<"No Solution"<<endl;
    64         return 0;
    65     }
    66     if(flag!=100) dfs(flag, 1);
    67     else dfs(minn,1);
    68     for(i = 1; i <= n+1; i++){
    69         cout<<ans[i];
    70     }
    71     cout<<endl;
    72     return 0;
    73 } 

    备注:

    欧拉路径就是一笔画,在图中仅有0或2个奇数入度点时存在。昨天下午看了半天求欧拉路径的算法,今天老师嘲讽一通说我看的是假的算法。。dfs+删边就可以了。虽然我很不愿意接受,但这么写写竟然是对的,而且效率还可以。

    为什么是对的很简单。从一个奇数入度点出发,如果全是偶数入度点,就从最小的点开始,dfs,走到无路可走时就找到了一个解。注意一定要回溯(否则走入一条死胡同就结束了),肯定不能一到某个点就输出这个点(此时不一定走的就是正确的路)这也是dfs加一个step参量的必要性(最后一次更新一定是正解)(回溯到这个点说明上一次从这个点出去选择的方向走不完图,所以换个方向走)。

    字典序很好办。从小到大搜就可以了。

    后来codevs过了,洛谷最后一个点过不了。看了一眼讨论,发现ans数组开小了。n的规模可以算,应该是52*52,开成2500就过了。

  • 相关阅读:
    ZipArchive 的使用
    Bootstrap使用心得
    SQL SERVER 级联删除
    ASP.NET 使用C#代码设置页面元素中的样式或属性
    GDI+中发生一般性错误之文件被占用
    .Net 中资源的使用方式
    一张图全解析个性化邮件那么重要
    看天猫EDM营销学企业EDM营销
    细数EDM营销中存在的两大盲点
    如何进行EDM邮件内容的撰写
  • 原文地址:https://www.cnblogs.com/fangziyuan/p/6940742.html
Copyright © 2011-2022 走看看