zoj 3816 Generalized Palindromic Number

        题意:给一个数n,求一个比n小的最大的数,使得这个数把相邻的相同数合并之后,是一个回文数。

        思路:dfs+剪枝。从高位到低位,从9~0尝试填数构造,如果可行就往下搜。dfs的过程也是构造的过程,需要剪枝,写两个函数,一个判断这个可能没构造完成的数是否可能构造出回文,另一个判断往后构造出来的数是否可能小于n,把不符合上面其中一种情况的分支剪掉。。。具体见代码。我写的时候是否可能构造出回文的判断就调试了很久。


#include<iostream>
#include<cmath>
#include<queue>
#include<vector>
#include<algorithm>
#include<string.h>
#include<cstdio>

using namespace std;

#define ll long long

int num[20];
int ans[20];
int len;

//判断这个可能尚未构造完成的数,有没有可能是回文数
bool judge(int* b,int pos){
    if(pos==0)return 1;
    int a[20];
    memcpy(a,b,len*sizeof(int));
    for(int i=1;i<len;i++){
        int l=i,r=i;
        do{
            if(a[l]!=a[r]&&a[r]!=-1)break;
            while(l>0&&a[l-1]!=-1&&a[l-1]==a[l])l--;
            while(r<len-1&&a[r+1]!=-1&&a[r+1]==a[r])r++;
            if(l>0&&r<len-1){
                l--;    r++;
            }
        }while(l!=0&&r!=len-1);
        while(r<len-1&&(a[r]==a[r+1]||a[r+1]==-1))r++;
        while(l>0&&a[l]==a[l-1])l--;
        if(l==0&&r==len-1&&(a[l]==a[r]||a[r]==-1)){
            return 1;
        }
    }
    return 0;
}

//判断a是否小于b
bool lessthan(int* a,int* b){
    for(int i=0;i<len;i++){
        if(a[i]>b[i])return 0;
        if(a[i]<b[i])return 1;
    }
    if(a[len-1]==b[len-1])return 0;
    return 1;
}


bool dfs(int pos,int *a,bool flag){
    if(pos==len){
        for(int i=0;i<len;i++)ans[i]=a[i];
        return 1;
    }

    int re[20];
    for(int i=0;i<len;i++)re[i]=-1;
    for(int i=0;i<pos;i++)re[i]=a[i];

    int s=9;
    if(!flag)s=num[pos];
    for(int i=min(s,9);i>=0;i--){
        if(!flag){
            if(i<num[pos])flag=1;
        }
        re[pos]=i;
        if(judge(re,pos)&&lessthan(re,num)){//只有可能是回文数且小于n的情况下才继续构造
            if(dfs(pos+1,re,flag))return 1;
        }
    }
    return 0;
}

int main(){
    int t;
    cin>>t;
    while(t--){
        ll n;
        cin>>n;
        if(n==1){
            cout<<0<<endl;
            continue;
        }
        ll tmp=n;
        len=0;
        while(tmp){
            num[len++]=tmp%10;
            tmp/=10;
        }
        for(int i=0;i<len;i++){
            ans[i]=0;
        }
        reverse(num,num+len);

        dfs(0,ans,0);
        if(ans[0]==0){
            for(int i=1;i<len;i++){
                printf("9");
            }printf("\n");
        }else{
            for(int i=0;i<len;i++){
                printf("%d",ans[i]);
            }printf("\n");
        }
    }
    return 0;
}


你可能感兴趣的:(DFS,剪枝)