程序師世界是廣大編程愛好者互助、分享、學習的平台,程序師世界有你更精彩!
首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫知識
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
 程式師世界 >> 編程語言 >> C語言 >> C++ >> C++入門知識 >> [數位dp] hdu 3886 Final Kichiku “Lanlanshu”

[數位dp] hdu 3886 Final Kichiku “Lanlanshu”

編輯:C++入門知識

[數位dp] hdu 3886 Final Kichiku “Lanlanshu”


題意:

在范圍內滿足所給的運算符的數有多少個。

“/” 代表前面的比後面的小 “-”代表前面和後面一樣 “\” 代表前面的比後面的大

測試過會出現重復的符號 比如 "///\"

思路:

細心啊細心啊。。!!

數位dp,按位dp

注意幾個點就好了:

1、n個運算符至少要有n+1個數。

2、注意開始的狀態,第一個數以及第一個運算符。

3、運算符後移注意移動到結束標識就直接返回0。

4、運算符能往後移就往後移。

5、注意大數減一的計算。

6、注意減法的取模。

代碼:

#include"cstdlib"
#include"cstdio"
#include"cstring"
#include"cmath"
#include"queue"
#include"algorithm"
#include"iostream"
using namespace std;
//2014年9月26日12:49:21
__int64 dp[102][102][12];
int num[102],m=100000000;  //因為8位數 所以對100000000取模
char v[102];
int ok(int n,int y,int z)
{
    if(n>=101) //特判101
    {
        if(n==101) n=0;
        else return 0;
    }
    if(v[n]=='\0') return 0; //注意如果字符串結束了 返回0
    char x=v[n];
    if(x=='/') return yz;
}
__int64 dfs(int site,int n,int cur,int zero,int f)  //位數,運算符,前一個數,前導零,是否是邊界
{
    if(site==0)
    {
        if(zero) return 0;
        int tep=strlen(v)-1;  //是否取到了最後一位
        return tep==n;
    }
    if(!f&&!zero&&~dp[site][n][cur]) return dp[site][n][cur];
    int len=f?num[site]:9;
    int ans=0;
    for(int i=0; i<=len; i++)
    {
        if(zero)
        {
            if(i==0) ans+=dfs(site-1,n,cur,zero&&i==0,f&&i==len);
            else
            {
                if(cur==10) ans+=dfs(site-1,101,i,zero&&i==0,f&&i==len);  //首先第一位直接放進去 然後因為只有一個數還不能確定運算符
                else
                {
                    if(ok(n+1,cur,i)) ans+=dfs(site-1,n+1,i,zero&&i==0,f&&i==len);  //這裡的原則是運算符能往後走就往後走
                    else if(ok(n,cur,i)) ans+=dfs(site-1,n==101?0:n,i,zero&&i==0,f&&i==len); //保持原樣,然後就是101代表第二個數 因為-1會越界
                }
            }
        }
        else
        {
            if(cur==10) ans+=dfs(site-1,101,i,zero&&i==0,f&&i==len);
            else
            {
                if(ok(n+1,cur,i)) ans+=dfs(site-1,n+1,i,zero&&i==0,f&&i==len);
                else if(ok(n,cur,i)) ans+=dfs(site-1,n==101?0:n,i,zero&&i==0,f&&i==len);
            }
        }
        ans%=m;
    }
    if(!f&&!zero) dp[site][n][cur]=ans;
    return ans;
}
__int64 solve(char *x,int f)  //f用來區分是否要減一
{
    int i=0,cnt=0;
    int len=strlen(x);
    while(x[i]=='0') i++;  //去前導0
    if(x[i]=='\0')  return 0;  //如果是0
    for(int j=len-1; j>=i; j--) num[++cnt]=x[j]-'0'; //放入num
    if(f) //減一
    {
        num[1]--;
        for(int j=1; j<=cnt; j++)
        {
            if(num[j]<0)
            {
                num[j]+=10;
                num[j+1]--;
            }
        }
    }
    if(num[cnt]==0) cnt--; //注意退位
    return dfs(cnt,101,10,1,1);
}
int main()
{
    while(scanf("%s",v)!=-1)
    {
        memset(dp,-1,sizeof(dp));
        char x[123],y[123];
        scanf("%s%s",x,y);  //比較長 要用字符串讀入
        printf("%08I64d\n",(solve(y,0)-solve(x,1)+m)%m); //減法一定注意取模。。
    }
    return 0;
}
//2014年9月26日19:08:24


  1. 上一頁:
  2. 下一頁:
Copyright © 程式師世界 All Rights Reserved