POJ 2718 搜索+思维

一道思维细节题,没有什么难点。这种题想到就行,没想到错误找一辈子.../(ㄒoㄒ)/~~

 

POJ 2718:http://poj.org/problem?id=2718

题意: 给出最多10个不重复的从小到大的个位数, 将它们任意组合为两个数字,不能有前导0。

            求出,所有排列中,两个数的最小差值。

 

网上很多人都是用new_permution还是什么的STL里的取排列办法直接爆搜。没有尝试也不想尝试。

我的心理进程是:

  两个数的要是差最小,那么他们的最高位肯定是给出的数字中相邻的两个数字。一个为小,一个为大。

  然后,高位较小的数字,后面放最大的数,依次放下去。

            低位较大的数字,后面放最小的数,依次放下去。

           那么它们的差就是最小的。

 

  比如说:   0 1 2 3 4 5

          那么最小差值肯定在这几个数字之中。

          154      203

          254      301

          352      401

          432      501

          而答案也正是 254 301。

        

         模拟一遍后WA了。想起来没考虑数字为奇数个时。

         于是添加上,当个数为奇数个时,剩下的那个数给小的数字加上。然后求差值

        即  01 2 3 4 5 6  

         就变为了    2654 301

         模拟一遍后WA了。 发现这思路根本就是错的啊!

       因为此时,最小的应该是  1023 654

       也就是,左边为最小的四位数,右边为最大的三位数

 

        终于开开心心的模拟完。交了一发,WA了...微笑

 

        要砸电脑了微笑    但是后来发现是细节上,n写成len了.....

 

       总结一下: 思路就是分为,输入的数字个数为奇数还是偶数。

                            若为奇数,则最小差为     最小多位数-最大低位数

                            若为偶数,则搜索任意两位相邻位为最高最低位,把数字填进去,搜索最小解

                           还要分类讨论一下,如果只有两个数字,就输出他们的差即可。

 

这题代码就很杂乱无章了。仅仅可借鉴思路:

 

 

#include"cstdio"
#include"cstring"
#include"queue"
#include"cmath"
#include"iostream"
#include"algorithm"
using namespace std;
#define inf 999999999
#define loop(x,y,z) for(x=y;x<z;x++)

int pos[10],n;
int ans;
int book[10];

void dfs(int m)
{
    if(m==n-1)return;
    if(m==0&&pos[m]==0)
    {
        dfs(m+1);return;
    }
    int l=pos[m];
    int r=pos[m+1];
    book[m]=book[m+1]=1;
    int i,j;
    int t=n/2;

    for(i=0,j=1;j<t;i++)
    if(!book[i])
    {
        book[i]=1;
        r=r*10+pos[i];
        j++;
    }

    for(i=n-1,j=1;j<t;i--)
    if(!book[i])
    {
        book[i]=1;
        l=l*10+pos[i];
        j++;
    }
    int sum=r-l;
    ans=min(ans,sum);
    memset(book,0,sizeof book);
    dfs(m+1);
}

void odd_cal()
{
    int l=0;
    int r=0;
    if(pos[0]==0)
        l=pos[1]*10;
    else l=pos[0]*10+pos[1];
    int i;
    loop(i,2,n/2+1)
        l=l*10+pos[i];
    for(int j=n-1;j>=i;j--)
        r=r*10+pos[j];
    ans=min(ans,l-r);
}

int main()
{
    int i,T,len;
    char str[100];
    scanf("%d",&T);getchar();
    while(T--)
    {
        ans=inf;
        memset(book,0,sizeof book);
        gets(str);
        len=strlen(str);
        n=0;
        loop(i,0,len)
        if(str[i]!=' ')
            pos[n++]=str[i]-'0';

        if(n==2)
            ans=abs(pos[0]-pos[1]);
        else if(n%2==0)
            dfs(0);
        else
        odd_cal();
        printf("%d\n",ans);
    }
    return 0;
}

 

 

 

 

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值