题目链接:https://codeforces.com/problemset/problem/182/E
题目大意:有n个木板,每种类型木板有一个长x和宽y,如果同一个类型木板旋转后长x和宽y和之前一样,那么只能算做一个木板,否则可以算做同类型的不同木板。现在商店每种类型的木板有无数种。如果要搭建长度为l的篱笆。问有多少种方案。
必须满足:
1.连续的两块木板类型不能相同
2.除了第一块木板,后面的木板的长必须等于上一块木板的宽。
因为状态与最后一块木板有关系, 那么我们必须二维。
直接dp[i][j]:最后一块木板为j,搭长度为i的篱笆的方案数。
枚举上一块的篱笆k就可以转移了(k=0:上一块没有)。
#include <bits/stdc++.h>
#define LL long long
using namespace std;
const int mod=1e9+7;
struct node{
int x, y, k;
}a[205];
LL f[3005][205];
int main(){
int n, l, tot=1;
scanf("%d%d", &n, &l);
for(int i=1; i<=n; i++){
scanf("%d%d", &a[tot].x, &a[tot].y);
a[tot].k=i;
if(a[tot].x!=a[tot].y){
tot++;
a[tot].x=a[tot-1].y;
a[tot].y=a[tot-1].x;
a[tot].k=i;
}
tot++;
}
for(int i=1; i<=l; i++){
for(int j=1; j<tot; j++){
for(int k=0; k<tot; k++){
if(a[j].k==a[k].k){
continue;
}
if(k==0&&a[j].x==i){
f[i][j]++;
f[i][j]%=mod;
}
else if(a[j].x==a[k].y&&i>a[j].x){
f[i][j]+=f[i-a[j].x][k];
f[i][j]%=mod;
}
}
}
}
LL ans=0;
for(int i=1; i<tot; i++){
ans=(ans+f[l][i])%mod;
}
printf("%lld\n", ans);
return 0;
}