小明的密碼-初級DP解法

#include
#include
#include
using namespace std;
int visited[5][20][9009];// 訪問狀況
int dp[5][20][9009];  // M N num num即M-1位的數字
int num_2[7]= {2,3,5,7,11,13,17};
int num_3[9]= {2,3,5,7,11,13,17,19,23};
int num_4[11]= {2,3,5,7,11,13,17,19,23,29,31};  //存儲素數
int N,M;
int delete_head(int num,int m)  //去掉當前數字的首個數字
{
    int ans;
    if (m==2) return 0;
    if (m==3) ans=num-num/10*10;
    if (m==4) ans=num-num/100*100;
    return ans;
}
int divide_num(int num)
{
    int ans=0;
    while (num>0)
    {
        ans+=num;
        num=num/10;
    }
    return ans;
}
int select_num(int k,int sum,int m)
{
    if (m==2)
    {
        for (int i=0; i<7; i++) if (k+divide_num(sum)==num_2[i]) return 1;
        return 0;
    }
    if (m==3)
    {
        for (int i=0; i<9; i++)
            if (k+divide_num(sum)==num_3[i])
            {
                return 1;
            }
        return 0;
    }
    if (m==4)
    {
        for (int i=0; i<11; i++) if (k+divide_num(sum)==num_4[i]) return 1;
        return 0;
    }
}
void work(int m,int n,int num)
{
    if (n==0)  // n=0直接處理
    {
        visited[m][n][num]=1;
        dp[m][n][num]=1;
    }
    else
    {
        if (!visited[m][n][num])
        {
            visited[m][n][num]=1;
            for (int k=0; k<=9; k++)
            {
                if (select_num(k,num,m))
                {
                    int next=delete_head(num,m)*10+k; //next是num的下個狀態(去頭加尾)
                    if (!visited[m][n-1][next])
                    {
                        work(m,n-1,next);
                    }
                    dp[m][n][num]+=dp[m][n-1][next];
                }
            }
        }
    }
}
int main()
{
    memset(visited,0,sizeof(visited));
    memset(dp,0,sizeof(dp));
    scanf("%d %d",&N,&M);
    if (M==1)
    {
        int ans=1;
        while (N>0)
        {
            ans*=4;
            N--;
        }
        printf("%d\n",ans);
    }
    if (M==2)
    {
        int ans=0;
        for (int i=0; i<=9; i++)
        {
            int num=i;
            work(M,N-1,num);
            ans+=dp[M][N-1][num];
        }
        printf("%d\n",ans);
    }
    if (M==3)
    {
        int ans=0;
        for (int i=0; i<=9; i++)
            for (int k=0; k<=9; k++)
            {
                int num=i*10+k;
                work(M,N-2,num);
                ans+=dp[M][N-2][num];
            }
        printf("%d\n",ans);
    }
    if (M==4)
    {
        int ans=0;
        for (int i=0; i<=9; i++)
            for (int k=0; k<=9; k++)
                for (int x=0; x<=9; x++)
                {
                    int num=i*100+k*10+x;
                    work(M,N-3,num);
                    ans+=dp[M][N-3][num];
                }
        printf("%d\n",ans);
    }
    return 0;
}

  

小明的密碼由N(1<=N<=12)個數字構成,每一個數字均可以是0至9中任意一個數字,但小明的密碼還有 一個特色就是密碼中連續的M(1<=M<=4)個數字的和是質數,現給定M和N,求知足條件的密碼共有多少 個? 輸入格式 第1行是T,case數量,此後T行,每行兩個數,N和M 輸出格式 每一個case輸出一個知足條件的密碼總數 
輸入樣例 
1 1 
2 1 
輸出樣例 
16 
做者 admin
第一次作多維DP,雖然才作到第三個維度,感受已經夠狠的題目還能夠出的更復雜,好比M更大的時候我還沒想過怎麼操做,暫時作到三維DP,主要是作第三維的時候遇到困難,第一次作的時候把前M-1位的數字和求出來作參數,沒想到維度混淆了,仍是隻能用M-1作真整數,這樣若是M稍微大一點,我可能都要作高精度了,並且內存也不寬裕,繼續努力想其餘解法吧
  1 #include <cstdlib>
  2 #include <cstdio>
  3 #include  <cstring>
  4 using namespace std;
  5 int visited[5][20][9009];// 訪問狀況
  6 int dp[5][20][9009];  // M N num num即M-1位的數字
  7 int num_2[7]= {2,3,5,7,11,13,17};
  8 int num_3[9]= {2,3,5,7,11,13,17,19,23};
  9 int num_4[11]= {2,3,5,7,11,13,17,19,23,29,31};  //存儲素數
 10 int N,M;
 11 int delete_head(int num,int m)  //去掉當前數字的首個數字
 12 {
 13     int ans;
 14     if (m==2) return 0;
 15     if (m==3) ans=num-num/10*10;
 16     if (m==4) ans=num-num/100*100;
 17     return ans;
 18 }
 19 int divide_num(int num)
 20 {
 21     int ans=0;
 22     while (num>0)
 23     {
 24         ans+=num;
 25         num=num/10;
 26     }
 27     return ans;
 28 }
 29 int select_num(int k,int sum,int m)
 30 {
 31     if (m==2)
 32     {
 33         for (int i=0; i<7; i++) if (k+divide_num(sum)==num_2[i]) return 1;
 34         return 0;
 35     }
 36     if (m==3)
 37     {
 38         for (int i=0; i<9; i++)
 39             if (k+divide_num(sum)==num_3[i])
 40             {
 41                 return 1;
 42             }
 43         return 0;
 44     }
 45     if (m==4)
 46     {
 47         for (int i=0; i<11; i++) if (k+divide_num(sum)==num_4[i]) return 1;
 48         return 0;
 49     }
 50 }
 51 void work(int m,int n,int num)
 52 {
 53     if (n==0)  // n=0直接處理
 54     {
 55         visited[m][n][num]=1;
 56         dp[m][n][num]=1;
 57     }
 58     else
 59     {
 60         if (!visited[m][n][num])
 61         {
 62             visited[m][n][num]=1;
 63             for (int k=0; k<=9; k++)
 64             {
 65                 if (select_num(k,num,m))
 66                 {
 67                     int next=delete_head(num,m)*10+k; //next是num的下個狀態(去頭加尾)
 68                     if (!visited[m][n-1][next])
 69                     {
 70                         work(m,n-1,next);
 71                     }
 72                     dp[m][n][num]+=dp[m][n-1][next];
 73                 }
 74             }
 75         }
 76     }
 77 }
 78 int main()
 79 {
 80     memset(visited,0,sizeof(visited));
 81     memset(dp,0,sizeof(dp));
 82     scanf("%d %d",&N,&M);
 83     if (M==1)
 84     {
 85         int ans=1;
 86         while (N>0)
 87         {
 88             ans*=4;
 89             N--;
 90         }
 91         printf("%d\n",ans);
 92     }
 93     if (M==2)
 94     {
 95         int ans=0;
 96         for (int i=0; i<=9; i++)
 97         {
 98             int num=i;
 99             work(M,N-1,num);
100             ans+=dp[M][N-1][num];
101         }
102         printf("%d\n",ans);
103     }
104     if (M==3)
105     {
106         int ans=0;
107         for (int i=0; i<=9; i++)
108             for (int k=0; k<=9; k++)
109             {
110                 int num=i*10+k;
111                 work(M,N-2,num);
112                 ans+=dp[M][N-2][num];
113             }
114         printf("%d\n",ans);
115     }
116     if (M==4)
117     {
118         int ans=0;
119         for (int i=0; i<=9; i++)
120             for (int k=0; k<=9; k++)
121                 for (int x=0; x<=9; x++)
122                 {
123                     int num=i*100+k*10+x;
124                     work(M,N-3,num);
125                     ans+=dp[M][N-3][num];
126                 }
127         printf("%d\n",ans);
128     }
129     return 0;
130 }
View Code
相關文章
相關標籤/搜索