题意
给了 n 种类型的木板,每种类型的木板数量无限,可以随意旋转,现在要用这些木板组成一个 fence,fence 的长度必须刚好是 L,并且需要满足两个要求:
1、相邻的木板不能同种类
2、前一个板子的宽度必须是后一个板子的长度
现在问你能组成多少种 fence 满足上面的条件
做法分析
动态规划,长度类型的,以长度划分阶段,每个阶段的状态可以这样定义:f[L][[i] 表示已经拼凑成了一个长度为 L 的,最后一个木板是第 i 个,有多少种不同的fence。这里需要做一个处理:如果一个木板的长度和宽度不等,那么,就再生成一个木板,这个木板的宽度是原来木板的长度,长度是原来木板的宽度,类型和原来的木板类型相同,所以便有了上面的阶段划分和状态转移
AC通道
参考代码
#include <cstdio>
#include <iostream>
#include <cstring>
#include <cmath>
using namespace std;
const int N=250;
const int MOD=1000000007;
struct data
{
int type;
int width, length;
} a[N];
int f[3050][250], n, cnt, m;
int main()
{
memset(f, 0, sizeof(f));
scanf("%d%d", &n, &m);
cnt=n;
for(int i=1, L, W; i<=cnt; i++)
{
scanf("%d%d", &L, &W);
a[i].length=L, a[i].width=W, a[i].type=i;
f[L][i]=(f[L][i]+1)%MOD;
if(L!=W)
{
n++;
a[n].length=W, a[n].width=L, a[n].type=i;
f[W][n]=(f[W][n]+1)%MOD;
}
}
for(int L=0; L<=m; L++)
for(int i=1; i<=n; i++)
for(int j=1; j<=n; j++)
if(a[i].type!=a[j].type && a[j].width==a[i].length && L>=a[i].length)
{
f[L][i]=(f[L][i]+f[L-a[i].length][j])%MOD;
}
int ans=0;
for(int i=1; i<=n; i++)
ans=(ans+f[m][i])%MOD;
printf("%d\n", ans);
return 0;
}