hdu6468(记忆化搜索)

zyb的面试

Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 65536/65536 K (Java/Others)
Total Submission(s): 695    Accepted Submission(s): 254


Problem Description
今天zyb参加一场面试,面试官听说zyb是ACMer之后立马抛出了一道算法题给zyb:
有一个序列,是1到n的一种排列,排列的顺序是字典序小的在前,那么第k个数字是什么?
例如n=15,k=7, 排列顺序为1, 10, 11, 12, 13, 14, 15, 2, 3, 4, 5, 6, 7, 8, 9;那么第7个数字就是15.
那么,如果你处在zyb的场景下,你能解决这个问题吗?
 

 

Input
T组样例(T<=100)
两个整数n和k(1<=n<=1e6,1<=k<=n),n和k代表的含义如上文
 

 

Output
输出1-n之中字典序第k小的数字
 

 

Sample Input
1 15 7
 

 

Sample Output
15
 

 

Source
 
 
思路:见代码
#include<cstdio>
#include<algorithm>
using namespace std;
int dis[10];//把n分解 
int cnt,len,ans,k,n;
bool lg1;
int ws[10];//判断每一位都取值时最终的值是否可能超过n 
int dp[10];//取到底的记忆化 
int les[10];//不取到底的记忆化(当前值已经大于n并且还没到底,就返回了) 
int dfs(int pos,int sum,int po){//sum*po为当前值,ws[pos]为上界,
    if(sum*po<ws[pos]&&dp[pos]!=-1&&(cnt+dp[pos]<k)){//当找的范围还在k内 
        cnt+=dp[pos];//当当前值小于上界时,就记忆化每一位都取的情况 
        return dp[pos];
    }
    else if(sum*po>ws[pos]&&les[pos]!=-1&&(cnt+les[pos]<k)){
        cnt+=les[pos];//当当前值大于上界,就记忆化至少有一位不选的情况(当至少有一位没取时可以保证 
        return les[pos];//最后得到的值一定小于n 
    }
    int sum2=cnt;
    int sum1=0;
    if(sum<=n){//当当前值满足条件时 
        sum1++;
        cnt++;
        if(cnt==k){
            ans=sum;
            lg1=false;
            return 0;
        }
    }
    else
    return 0;
    if(pos==0)
    return sum1;
    for(int i=0;i<=9&&lg1;i++){//往下走 
        sum1+=dfs(pos-1,sum*10+i,po/10);
    }
    //printf("%d %d\n",sum*po,ws[pos]);
    if(sum*po<ws[pos])//当没有到上界 
    dp[pos]=sum1;
    else if(sum*po>ws[pos])//当到上界 
    les[pos]=cnt-sum2;
    return sum1;
}
int main(){
    int t;
    scanf("%d",&t);
    while(t--){
        cnt=0;
        scanf("%d%d",&n,&k);
        len=0;
        fill(dp,dp+8,-1);
        fill(les,les+8,-1);
        int m=n;
        int po=1;
        while(m){
            po*=10;
            dis[++len]=m%10;
            m/=10;
        }
        int r=1;
        int summ=0;
        for(int i=1;i<len;i++){
            summ+=dis[i]*r;
            ws[i]=n-summ;
            r*=10;            
        }
        lg1=true;
        for(int i=1;i<=9&&lg1;i++){
            dfs(len-1,i,po/10);
        }    
        printf("%d\n",ans);
    }
    return 0;
}

 

posted @ 2019-05-12 16:49  cglong  阅读(274)  评论(0编辑  收藏  举报