pku3359

 对于给定的一个字符串,计算其按字典序排列的全排列中以改字符串为中心的21个字符串中,每个字符串中相邻两个字符直接距离绝对值的最小值,在这21个字符串中这个最小值最大的那个。唉,不管怎么说都是这么绕,还是用原文吧:which has the largest minimum absolute distance between consecutive letters (and the first amongst the lexicographically ordered, if several permutations have the largest minimum absolute distance), followed by that minimum absolute distance.

就是这绕来绕去的题目,看的都头大,结过把蓝色部分竟然看成是输出具有相同最大最小绝对距离字符串的数目,WA了N次……

无路之下重新看题才发现自己竟然载在english上……

最开始自己写的求排列的函数,花了好长时间才分析出规律:

Source:

 

#include < iostream >
using   namespace  std;

int  main()
{
    
char  str[ 30 ],data[ 25 ][ 30 ];
    
int  i,j,k,s,mx,p,len,mi,tot;

    
while (cin.getline(str, 30 , ' ' ))
    {
        len
= strlen(str);
        strcpy(data[
11 ],str);
        
// forward
         for (i = 10 ;i >= 1 ; -- i)
        {
            
for (j = len - 1 ;j > 0 ; -- j)
            {
                
if (str[j - 1 ] > str[j])
                {
                    mx
= str[j];p = j;
                    
for (k = j + 1 ;k < len; ++ k)
                    {
                        
if (str[k] < str[j - 1 &&  str[k] > mx)
                        {
                            mx
= str[k];p = k;
                        }
                    }
                    str[p]
= str[j - 1 ];
                    str[j
- 1 ] = mx;
                    
for (k = j;k < len; ++ k)
                    {
                        mx
= str[k];p = k;
                        
for (s = k + 1 ;s < len; ++ s)
                        {
                            
if (str[s] > mx)
                            {
                                mx
= str[s];p = s;
                            }
                        }
                        str[p]
= str[k];
                        str[k]
= mx;
                    }
                    strcpy(data[i],str);
                    
break ;
                }
            }
            
if (j == 0 )strcpy(data[i],str);
        }

        
// backward
        strcpy(str,data[ 11 ]);
        
for (i = 12 ;i <= 21 ; ++ i)
        {
            
for (j = len - 1 ;j > 0 ; -- j)
            {
                
if (str[j - 1 ] < str[j])
                {
                    mi
= str[j];p = j;
                    
for (k = j + 1 ;k < len; ++ k)
                    {
                        
if (str[k] > str[j - 1 &&  str[k] < mi)
                        {
                            mi
= str[k];p = k;
                        }
                    }
                    str[p]
= str[j - 1 ];
                    str[j
- 1 ] = mi;
                    
for (k = j;k < len; ++ k)
                    {
                        mi
= str[k];p = k;
                        
for (s = k + 1 ;s < len; ++ s)
                        {
                            
if (str[s] < mi)
                            {
                                mi
= str[s];p = s;
                            }
                        }
                        str[p]
= str[k];
                        str[k]
= mi;
                    }
                    strcpy(data[i],str);
                    
break ;

                }
            }
            
if (j == 0 )strcpy(data[i],str);
        }

        
for (i = 1 ,mx = 0 ,p = 1 ,tot = 0 ;i <= 21 ; ++ i)
        {
            mi
= data[i][ 1 ] - data[i][ 0 ];
            mi
= mi > 0 ? mi: - mi;
            
for (j = 1 ;j <= len - 2 ; ++ j)
            {
                k
= data[i][j + 1 ] - data[i][j];
                k
= k > 0 ? k: - k;
                
if (k < mi)mi = k;
            }
            
if (mi > mx)
            {
                mx
= mi;p = i;tot = 1 ;
            }
else   if (mi == mx)
            {
                tot
++ ;
            }
        }
        
// for(i=1;i<=21;++i)cout<<data[i]<<endl;
        cout << data[p] << mx << endl;
    }
    
return   0 ;
}

后来发现STL中有prev_permutation和next_permutation两个函数,重写一遍,早知道那还有去浪费脑细胞……

Source:

 

#include < iostream >
#include
< algorithm >
using   namespace  std;

char  str[ 30 ],res[ 30 ],ori[ 30 ];
int  i,k,len,mi,mx,j;

int  main()
{
    
while (cin >> str)
    {
        strcpy(ori,str);
        len
= strlen(str);
        mi
= str[ 1 ] - str[ 0 ];
        mi
= (mi > 0 ) ? mi: - mi;
        strcpy(res,str);
        
for (i = 2 ;i < len; ++ i)
        {
            k
= str[i] - str[i - 1 ];
            k
= (k > 0 ) ? k: - k;
            
if (k < mi)
            {
                mi
= k;
            }
        }
        mx
= mi;
        
for (j = 0 ;j < 10 ; ++ j)
        {
            
if (prev_permutation(str,str + len))
            {
//                 cout<<-j<<":"<<str<<endl;
                mi = str[ 1 ] - str[ 0 ];
                mi
= (mi > 0 ) ? mi: - mi;
                
for (i = 2 ;i < len; ++ i)
                {
                    k
= str[i] - str[i - 1 ];
                    k
= (k > 0 ) ? k: - k;
                    
if (k < mi)
                    {
                        mi
= k;
                    }
                }
                
if (mi >= mx)
                {
                    mx
= mi;
                    strcpy(res,str);
                }
            }
        }
        strcpy(str,ori);
//         cout<<str<<endl;
         for (j = 0 ;j < 10 ; ++ j)
        {
            
if (next_permutation(str,str + len))
            {
//                 cout<<j<<":"<<str<<endl;
                mi = str[ 1 ] - str[ 0 ];
                mi
= (mi > 0 ) ? mi: - mi;
                
for (i = 2 ;i < len; ++ i)
                {
                    k
= str[i] - str[i - 1 ];
                    k
= (k > 0 ) ? k: - k;
                    
if (k < mi)
                    {
                        mi
= k;
                    }
                }
                
if (mi > mx)
                {
                    mx
= mi;
                    strcpy(res,str);
                }
            }
        }
        cout
<< res << mx << endl;
    }
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值