【Algorithm】动态规划实例五 Making N Dollars

来源:互联网 发布:电脑淘宝网页有问题 编辑:程序博客网 时间:2024/04/29 20:12


You have the infinite number of bills from 1 dollar through to K dollars. You want to know all possible ways of making N dollars using all other bills except N dollars. For example, when you have 1, 2, 3 dollars, there are five ways of making 5 dollars.


$1 x 5

$2 x 1 + $1 x 3

$2 x 2 + $1 x 1

$3 x 1 + $1 x 2

$3 x 1 + $2 x 1


If N dollars that you want to make and the largest dollar bill, K, are given, create a calculation program that finds out how many ways of making N dollars exist.


Time limits: 1 second (java: 2 seconds)


[Input]

Input may include many test cases. The number of test cases, T, is given on the first line of input and then the amount of T of test cases is given in a line. (T ≤ 20)
N dollar that you want to make and the largest K dollars of your infinite belonging are given separately as blanks for the first line of each test case. (1 ≤ N ≤ 1000, 1 ≤ K ≤ 100)


[Output]

Output the number of ways of making N dollars on the first line of each test case. As the number of cases can increase, divide it by 100 million and output the rest number of cases.


[I/O Example]

Input

2
5 3
10 2


Output

5
6


[Analysis]

If you denote number of ways of making N dollars with K bills (including $N bill) by W(N,K), then 

W(N,K) = W(N,K-1) + W(N-K, K), for K <= N

W(N,K) = W(N,K-1) for K > N

with

W(0 or 1, K) = 1

W(N, 1) = 1

 

In other words, you hide the highest bills, and check what you can do without them (that is W(N,K-1)).

Then you take one of the highest bills, and check what you can do to gather the rest (that is W(N-K,K)).

Bills higher than the target do not increase number of ways (that is W(N,K) = W(N, K-1) for K>N).

 

For example, when you want to make 10 dollars from bills $1..$3, then number of ways is sum of numbers of ways of:

- making 10 dollars from bills $1..$2;

- making 7 (=10-3) dollar from bills $1..$3.

 

One tweak for that is that you cannot use $10 bill for making 10 dollars. But that is only one subtraction at the end, when needed.

这道题看了好几个解法,这个是看懂的,不过也不是理解的很透彻。

公式大概可以理解,F[i][j] 表示j枚硬币总价值为i时的次数。

假设第j个硬币里最大的拿出来,加入组合。这里硬币是连续的,那j本身就是最大的,那就F[i-j][j-1], 数量要减1,总价值减j

假设第j个硬币里最大的拿出来,并不加入组合。那就是F[i][j-1],数量减1,总价值不减。

以上的前提是i>=j,使得j有被加入的可能。

这里的j的价值要小于所求i的价值,如果大了,就直接F[I][j],因为j直接就不在考虑中。

公式有了F[i][j] =F[i-j][j-1]+F[i][j-1] (i>=j)

F[i][j] =F[I][j-1] (i<j)


[Answer]

// In Practice, You should use the statndard input/output
// in order to receive a score properly.
// Do not use file input and output. Please be very careful.
#define _CRT_SECURE_NO_WARNINGS

#include <stdio.h>
#include <string.h>
#define M 1005
int N, K;
int F[M][M];
int Answer;

int main(void)
{
 int tc, T;

 // The freopen function below opens input.txt file in read only mode, and afterward,
 // the program will read from input.txt file instead of standard(keyboard) input.
 // To test your program, you may save input data in input.txt file,
 // and use freopen function to read from the file when using scanf function.
 // You may remove the comment symbols(//) in the below statement and use it.
 // But before submission, you must remove the freopen function or rewrite comment symbols(//).

 // freopen("input.txt", "r", stdin);

 // If you remove the statement below, your program's output may not be rocorded
 // when your program is terminated after the time limit.
 // For safety, please use setbuf(stdout, NULL); statement.

 setbuf(stdout, NULL);

 scanf("%d", &T);
 for (tc = 0; tc < T; tc++)
 {
  Answer = 0;
  memset(F,0,sizeof(F));
  scanf("%d", &N);
  scanf("%d", &K);

  int i, j;  

  for (j = 0; j <= K; j++)
  {
   F[0][j] = 1;
  }

  for (i = 1; i <= N;i++)
  {
   for (j = 1; j<=K; j++)
   {
    if (i >= j)
    {
     F[i][j] =( F[i][j - 1] + F[i - j][j]) %100000000;
    }
    else
    {
     F[i][j] = (F[i][j - 1])%100000000;
    }
   }
  }

  for (i = 1; i <= N; i++)
  {
   for (j = 1; j <= K; j++)
   {
    printf("%d", F[i][j]);
   }
   printf("\n");
  }
  printf("%d\n", F[N][K]);

 }

 return 0;//Your program should return 0 on normal termination.
}


0 0
原创粉丝点击