换钱的方法数

//暴力轮询的方法
int process1(int arr,int index,int aim)
{
    int res = 0;
    if(index == arr.size())
    {
        res = aim == 0?1:0//退出条件
    }
    else
    {
        for(int i=0;arr[index] * i <=aim;i++)
        {
            res += process1(arr,index+1,aim-arr[index]*i)
        }
    }
    return res;
}
/*  0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20
  |--------------------------------------------
5 | 1 0 0 0 0 1 0 0 0 0 1  0  0   0  0  1  0  0  0  0  1 
3 | 1 0 0 0 0 1 0 0 1 0 1  1  0   1  1  1  1  1  1  1  2 
2 | 1 0 0 0 0 1 1 1 2 2 3  4  4   5  6  7  8  9  10 11 13 
*/
int changeFormoney()
{
        int aim = 20;
    int money[3] = {5,3,2};
    int i,j;
    int dp[3][21]={{0,},{0,}};
    for(i=0;i<3;i++)
    {
        dp[i][0] = 1;//钱数为零时,只有一种方法,就是每一种都为0
    }
    /*dp[i][j]代表什么?存在money[0...i]种货币组成j元的种数*/
    /*先组合第一行*/
    for(j=0;j<=aim;j++)
    {
        dp[0][j*money[0]]=1;            
    }
    int numm = 0,k=0;//记录不用此面值钞票剩下的
    for(i=1;i<3;i++)
    {
        for(j=1;j<=aim;j++)
        {   
            numm = 0;
            for(k=0;j-money[i]*k>0;k++)//使用money[i]这种货币从1张到k张时的所有的方法总和3
            {
                numm += dp[i-1][j-money[i]*k];//j-money[i]*k可以这么理解,比如j=8,此时用0个3,组不成;用一个3,需要一个5,查看上一行面值为5的是否可以,发现dp[0][5]等于1,可以组成
            }
            dp[i][j] = numm;//不为0的位置就是可以组成的位置,在比如i=2,还是j=8.使用0个2,查看dp[1][8]为1,可以组成;使用一个2,查看dp[1][6]位0,组不成;使用两个2,查看dp[1][4]组不成;一次类推在dp[0][0]出还可以此时使用了4个2;
        }                   //dp[1][8]+dp[1][6]+dp[1][4]+dp[1][2]+dp[1][0] 
    }                      //dp[i-1][j-money[i]*k]
    printf("\r\n");
    for(i=0;i<3;i++)
    {
        for(j=0;j<=aim;j++)
        {
            printf("%d ",dp[i][j]);
        }
        printf("\r\n");
    }
    return 0;
}

猜你喜欢

转载自blog.csdn.net/caogenwangbaoqiang/article/details/80777182
今日推荐