数位dp+LIS+状态压缩-hdu-4352-XHXJ's LIS

来源:互联网 发布:sql join 编辑:程序博客网 时间:2024/05/20 23:06

题目链接:

http://acm.hdu.edu.cn/showproblem.php?pid=4352

题目意思:

求区间L到R之间的数A满足A的的数位的最长递增序列的长度为K的数的个数。

解题思路:

数位dp+LIS+状态压缩

根据求LIS的nlogn的思想,由于k最多为10,也就是最长递增序列的长度最多为10,可以状态压缩10位,维护前面的已选的递增序列,并及时更新。

dp[i][j][k]表示后面还有i位,前面状态为k,总共需要最长递增序列为j时的总数。

代码:

更新时用两种方式实现都可以。

#include<iostream>#include<cmath>#include<cstdio>#include<cstdlib>#include<string>#include<cstring>#include<algorithm>#include<vector>#include<map>#include<set>#include<stack>#include<list>#include<queue>#include<ctime>#define eps 1e-6#define INF 0x3fffffff#define PI acos(-1.0)#define ll __int64#define lson l,m,(rt<<1)#define rson m+1,r,(rt<<1)|1#pragma comment(linker, "/STACK:1024000000,1024000000")using namespace std;ll dp[25][12][1200];int bit[25],cnt,k;ll dfs(int cur,int s,int flag,int num,int * a){    if(!cur)    {        if(num==k)        {            dp[cur][num][s]=1;            return 1;        }        return 0;    }    if(!flag&&dp[cur][k][s]!=-1)        return dp[cur][k][s];    ll res=0;    int Max=flag?bit[cur]:9;    int tmp[25];    for(int i=0;i<=Max;i++)    {        for(int j=0;j<=num;j++) //如果用二分来写的话,要防止后面最前面数组的改动            tmp[j]=a[j];        if(!s&&!i) //注意前置零,不能记为一个数字        {            res+=dfs(cur-1,0,0,0,tmp);            continue;        }         //但当首位不为0时,0又是一个有效的数字        if(i>tmp[num]) //找到一个        {            tmp[num+1]=i;            res+=dfs(cur-1,s|(1<<i),flag&&(i==Max),num+1,tmp);        }        else        {   //找到第一个大于等于的            int t=lower_bound(tmp,tmp+num+1,i)-tmp;            int tt=tmp[t];            tmp[t]=i;            res+=dfs(cur-1,s-(1<<tt)+(1<<i),flag&&(i==Max),num,tmp);        } //第二种实现方式,比较直观,而且复杂度稍微低点/*        if((1<<i)>s)            res+=dfs(cur-1,s|(1<<i),flag&&(i==Max),num+1);        else if((1<<i)&s)            res+=dfs(cur-1,s,flag&&(i==Max),num);        else        {            for(int j=i+1;j<=9;j++)            {                if((1<<j)&s)                {                    res+=dfs(cur-1,(s-(1<<j))|(1<<i),flag&&(i==Max),num);                    break;                }            }        }*/    }    if(!flag)        dp[cur][k][s]=res;    return res;}ll init(ll a){    cnt=0;    while(a)    {        bit[++cnt]=a%10;        a/=10;    }    int aa[25];    aa[0]=-1;    return dfs(cnt,0,1,0,aa);}int main(){    memset(dp,-1,sizeof(dp));    int t;    ll a,b;    scanf("%d",&t);    for(int ca=1;ca<=t;ca++)    {        scanf("%I64d%I64d%d",&a,&b,&k);        //printf("%I64d %I64d\n",init(a,k),init(b,k));        printf("Case #%d: %I64d\n",ca,init(b)-init(a-1));    }   return 0;}



原创粉丝点击