前言:
对于动态规划来说,是小学乃至初中非常难的一类题型,状态转移方程是非常的难推,现在开始,我开了一个动归专栏。
(1)摆花(flower.pas)
{
题目: N 盆花中共有 M 种花,从 1 到 n 标号。为了展出更多种花, 规定第 i 种花不能超过 ai盆,摆花时同一种花放在一起,且不同种类的花需按标号的从小到 大的顺序依次摆列。
试编程计算,一共有多少种不同的摆花方案。
解题思路:已知i号花有ai个,所以三重循环分别枚举:
数量M、种数N、和当前的数量a[]
对于新来的花I,我们把它暂且看成未知数K(<=a[i])
}
STD:
var
n,m,i,j,k:longint;
f:array[0..100,0..100] of longint;//i为数量,j为当前数量的最优放花的种数
a:array[1..10000] of longint;
begin
readln(n,m);
for i:=1 to n do
read(a[i]);
f[0,0]:=1;//0盆花中有0种花,只有一种方法。
for i:=1 to n do//枚举N
for j:=m downto 0 do//枚举M,downto快一些
for k:=0 to a[i] do//枚举第i种花的数量(也可不取这盆花)
if j-k>=0 then//保证有解
f[i,j]:=(f[i,j]+f[i-1,j-k]) mod 1000007;
//当前状态=当前转移+【j-k:(j:上一种;k:上一些)没有用到这些花】
writeln(f[n,m]);//N盆、M种
end.
(2)平方数 (sqr.pas)
{
题目:对任意的正整数n,
把它分解为几个整数的平方之和(不包含零),
有多少种方案?
解题思路:三重循环分别枚举总数、当前平方数(末尾)、
一共有几种<=当前的平方数的数
样例说明:n=4
4=1*1+1*1+1*1+1*1 当前和=4,末尾=1*1;
}
STD:
var
n,m,i,j,k:longint;
a:array[1..1000] of longint;
f:array[0..800,0..800] of longint;//分别表示当前的总和和当前方案末尾的数
begin
readln(n);
f[0,1]:=1;//总数是零,当前末尾为1,只有一种方式。
for i:=1 to n do//枚举总和
for j:=1 to trunc(sqrt(n)) do//枚举sqrt(n)的平方数,上取整。
for k:=1 to j do
if i>=j*j then//保证有解
f[i,j]:=f[i,j]+f[i-j*j,k];//当前状态=当前转移+【当前总和排除当前平方数,现在新的末尾】
for i:=1 to trunc(sqrt(n)) do
m:=m+f[n,i];//把所有等于n的方案加起来
writeln(m);
end.
(3)神犇分牛(cows.pas)
{
题目:把m头牛放进n个房间,房间可以空着
问:总共有多少种方法(一共t次询问),答案可能较大,%100000007
思路:枚举一个房间中可能放牛的数量i,剩下的房间(k-1)可放牛的数量为j-i
}
STD:
var
i,j,m,n,k,t,p:longint;
f,f1:array[0..300,0..300] of longint;
begin
readln(t);
for p:=1 to t do
begin
readln(m,n);
f:=f1;
f[0,0]:=1;
for i:=0 to m do//一个房间的奶牛数
for j:=i to m do//奶牛总数
for k:=1 to n do//房间总数
f[j,k]:=(f[j,k]+f[j-i,k-1]) mod 100000007;
//当前状态=当前转移+【总房间放牛数-一个房间已经放牛数,那就少放一个房间】
writeln(f[m,n]);
end;
end.