hdu 4734 數位dp
阿新 • • 發佈:2018-02-03
枚舉 ets hdu eas ring stream urn 哈哈 mem
題意:For a decimal number x with n digits (AnAn-1An-2 ... A2A1), we define its weight as F(x) = An * 2n-1 + An-1 * 2n-2 + ... + A2 * 2 + A1 * 1. Now you are given two numbers A and B, please calculate how many numbers are there between 0 and B, inclusive, whose weight is no more than F(A).(懶得翻譯了哈哈哈)
題解:由於這裏要比較的是每個數位的帶權和,我們定義dp[i][j]為從i開始枚舉,和為j的時候有多少滿足題目意思的解
代碼:
#include <cstdio> #include <cstring> #include <iostream> #include <cmath> using namespace std; int a[20]; int dp[15][5100]; int len; int getsum(int x) { int tsum=0; int f=1; while(x) { tsum+=(x%10)*f; f*=2; x/=10; } return tsum; }int dfs(int pos,int sta,int key,bool limit) { if(pos==-1) return 1; if(!limit && dp[pos][sta]!=-1 ) return dp[pos][sta]; int up=limit ? a[pos] : 9; int sum=0; // cout<<pos<<" "<<up<<endl; for(int i=0;i<=up;i++) { int temp=sta+i*pow(2,pos); // cout<<temp<<endl; if(temp <= key) { sum+=dfs(pos-1,temp,key,limit & i==a[pos]); } } if(!limit) dp[pos][sta]=sum; // cout<<"pos: "<<pos<<" "<<"sta :"<<sta<<" "<<"sum :"<<sum<<endl; return sum; } int solve(int tempa,int b) { int akey=getsum(tempa); // cout<<akey<<endl; int pos=0; while(b) { a[pos++]=b%10; b/=10; } len=pos-1; return dfs(len,0,akey,true); } int main() { int t,Case=0; cin>>t; while(t--) { memset(dp,-1,sizeof(dp)); int aa,b; cin>>aa>>b; printf("Case #%d: %d\n",++Case,solve(aa,b)); } return 0; }
但是,這個會TLE,沒錯,會TLE.....
仔細看一下,每次我們都要初始話dp數組,代價有點大,但是按我們剛才的思路來的話,必須每次求的時候都初始話一次
換個思路,dp[i][j]表示枚舉到i這個位置的時候,還需要j才能滿足條件,這個時候dp數組就和輸入的數無關了(em..建議多理理這個不會太好理解)
AC代碼:
#include <cstdio> #include <cstring> #include <iostream> #include <cmath> using namespace std; int a[20]; int dp[15][5100]; int len; int getsum(int x) { int tsum=0; int f=1; while(x) { tsum+=(x%10)*f; f*=2; x/=10; } return tsum; } int dfs(int pos,int sta,bool limit)// 還需要sta { if(pos==-1) return sta>=0; if(sta < 0) return 0; if(!limit && dp[pos][sta]!=-1 ) return dp[pos][sta]; int up=limit ? a[pos] : 9; int sum=0; for(int i=0;i<=up;i++) { int temp=sta-i*(1<<pos); // cout<<temp<<endl; sum+=dfs(pos-1,temp,limit & i==a[pos]); } if(!limit) dp[pos][sta]=sum; // cout<<"pos: "<<pos<<" "<<"sta :"<<sta<<" "<<"sum :"<<sum<<endl; return sum; } int solve(int tempa,int b) { int akey=getsum(tempa); int pos=0; while(b) { a[pos++]=b%10; b/=10; } len=pos-1; return dfs(len,akey,true); } int main() { int t,Case=0; scanf("%d",&t); memset(dp,-1,sizeof(dp)); while(t--) { // int aa,b; scanf("%d %d",&aa,&b); printf("Case #%d: %d\n",++Case,solve(aa,b)); } return 0; }
hdu 4734 數位dp