日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

数位dp 记忆化搜索java_hdu 5787 数位dp,记忆化搜索

發布時間:2025/4/5 编程问答 34 豆豆
生活随笔 收集整理的這篇文章主要介紹了 数位dp 记忆化搜索java_hdu 5787 数位dp,记忆化搜索 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

題意:求區間[l,r]內有多少個數符合,這個數的任意的相鄰k位數(digits),這k個數都兩兩不相等

l,r范圍是1~1e18,k是2~5

思路:數位DP,因為K<=5,我們最多需要保存下來當前位的前4位就足夠了。因為dp[pos][p1][p2][p3][p4]表示,現在枚舉取第pos位,pos位之前的四位分別為p1,p2,p3,p4,p4是pos的上一位。那么p1~p4的范圍就是0~9,但是因為總位數小于當前數字的位數的數也要進行枚舉,需要一個數字來區分它是前導0還是在中間時為0,令p = 10是前導0,或者表示不需要儲存,即最高位的前幾位。那么dfs函數可以寫成?dfs( int pos , int p1 , int p2 , int p3 , int p4 , bool flag ) flag表示pos位能否取到全部的數位(0~9)還是會受到前面最高位的影響只能取一部分。

對于記憶化搜索首先明確代碼的dfs的定義為當前四位分別為p1,p2,p3,p4時枚舉第pos位總共有多少種方法,則dp方程很容易便能想到是1、pos位之前都取的0,即p4==10,而pos位也取0,一直都是前導零。2、而當p4!=10,pos位取的i去和p判斷一下有沒有重復(根據k來判斷需要比較幾個p),所以也是可以向下統計的,然后記得記憶化就好。

而dp的定義為當前四位數為p1,p2,p3,p4是枚舉pos位總共有多少種方法,這與dfs是不同的,因為對于dp 不需要考慮必須在小于當前數的范圍內進行枚舉,而dfs代表的方法數必須在小于當前數的范圍之內,這就可以解釋第38行。同時因為大多數情況下都是flag為假,隨意選擇記憶這種情況可以降低復雜度(這是我猜的,如果大家有別的想法可以說出來交流一下)

#include #include#include#include#include#include#include

using namespacestd;

typedeflong longll;const int N = 50000+10;const int mod=1e9+7;const double en=2.718281828459;

ll l,r,dp[20][11][11][11][11];int k,dig[20];bool cek(int u,int p1,int p2,int p3,intp4){if(k==2)return u!=p4;if(k==3)return u!=p4&&u!=p3;if(k==4)return u!=p4&&u!=p3&&u!=p2;if(k==5)return u!=p4&&u!=p3&&u!=p2&&u!=p1;

}

ll dfs(int pos,int p1,int p2,int p3,int p4,intflag){if(pos==0)return p4!=10;if(!flag&&dp[pos][p1][p2][p3][p4]!=-1) returndp[pos][p1][p2][p3][p4];//記憶化int ed=flag?dig[pos]:9;//當前面的數取小于其位置上的數顯然后面的數可以取0~9

ll ans=0;for(int i=0;i<=ed;i++){if(i==0&&p4==10)

ans+=dfs(pos-1,10,10,10,10,flag&&i==ed);else if(cek(i,p1,p2,p3,p4))

ans+=dfs(pos-1,p2,p3,p4,i,flag&&i==ed);

}if(!flag) dp[pos][p1][p2][p3][p4]=ans;returnans;

}

ll cal(ll u){int cnt=0;while(u>0){

dig[++cnt]=u%10;

u/=10;

}return dfs(cnt,10,10,10,10,1);

}intmain()

{//freopen("in.txt", "r", stdin);

while(~scanf("%lld %lld %d",&l,&r,&k)){

memset(dp,-1,sizeof(dp));

printf("%lld\n",cal(r)-cal(l-1));

}return 0;

}

總結

以上是生活随笔為你收集整理的数位dp 记忆化搜索java_hdu 5787 数位dp,记忆化搜索的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。