DP 有两种类型,一种是:Top-Down 一种是:Bottom-Up 。 DP 的典型的应用有几种:
1、Coin change : is the problem of finding the number of ways of making changes for a particular amount of cents,n, using a given set of denominations d[1...m].
The problem is defined follows:
Give an integer n, and a set of integers s={s[1],s[2]...s[m]} , How many ways can one express n as a linear combination of s[1..m] with non-negative coefficent.
Recursive formulation : f(n,m) = f(n,m-1) + f(n - i * s[m], m );
f(0,m) = 1 ; f(n<0,m) = 0 ; f(n>=1,m<=0)= 0;
问题:Square Coins
Time limit: 1 Seconds Memory limit: 32768K
People in Silverland use square coins. Not only they have square shapes but also their values are square numbers. Coins with values of all square numbers up to 289 (=17^2), i.e., 1-credit coins, 4-credit coins, 9-credit coins, ..., and 289-credit coins, are available in Silverland.
There are four combinations of coins to pay ten credits:
ten 1-credit coins,
one 4-credit coin and six 1-credit coins,
two 4-credit coins and two 1-credit coins, and
one 9-credit coin and one 1-credit coin.
Your mission is to count the number of ways to pay a given amount using coins of Silverland.
Input
The input consists of lines each containing an integer meaning an amount to be paid, followed by a line containing a zero. You may assume that all the amounts are positive and less than 300.
Output
For each of the given amount, one line containing a single integer representing the number of combinations of coins should be output. No other characters should appear in the output.
Sample Input
2
10
30
0
递归解法:
#include
<
iostream.h
>
int
A[
18
]
=
{
0
,
1
,
4
,
9
,
16
,
25
,
36
,
49
,
64
,
81
,
100
,
121
,
144
,
169
,
196
,
225
,
256
,
289
};
int
f(
int
,
int
);
main()
{
int
n;
cin
>>
n;
while
(n)
{
cout
<<
f(n,
17
)
<<
endl;
cin
>>
n;
}
return
0
;
}
int
f(
int
n,
int
m)
//
用最大面值为m*m的硬币组成n的方法数
{
if
(m
==
1
)
return
1
;
if
(n
==
0
)
return
1
;
int
sum
=
0
;
sum
+=
f(n,m
-
1
);
while
(n
>=
A[m])
{
n
-=
A[m];
sum
+=
f(n,m
-
1
);
}
return
sum;
}
DP 解法:
#include
<
iostream
>
using
namespace
std;
int
c[
301
][
18
];
void
init()
{
for
(
int
i
=
0
;i
<=
300
;i
++
)
for
(
int
j
=
0
;j
<=
17
;j
++
)
c[i][j]
=
0
;
c[
0
][
0
]
=
1
;
for
(
int
r
=
1
;r
<=
300
;r
++
)
for
(
int
l
=
1
;l
<=
17
;l
++
){
int
t
=
r,tt
=
l
*
l;
while
((t
-=
tt)
>=
0
)
for
(
int
k
=
0
;k
<
l;k
++
)
c[r][l]
+=
c[t][k];
}
}
int
count(
int
n)
{
int
sum
=
0
;
for
(
int
k
=
0
;k
<=
17
;k
++
) sum
+=
c[n][k];
return
sum;
}
int
main()
{
int
n;
init();
cin
>>
n;
while
(n){
cout
<<
count(n)
<<
endl;
cin
>>
n;
}
return
0
;
}