递推 dp
工大要建新教学楼了,一座很高很高的楼,它有n层。
学校为了减少排电梯的队伍,建造了好多好多电梯,共有m个。
为了让电梯有序,学校给每个电梯设定了独特的可停楼层,如 x1 x2 y1 y2 表示,x1楼层到x2楼层可停,y1楼层到y2楼层可停。然后其他楼层这个电梯都不停
一天,yanga11ang想去顶层观光,看到了如此多的电梯,不禁一阵眩晕,冒出疑问,如果只坐电梯,该如何去顶楼,有多少种方法可以去顶楼呢?
Ps:电梯只能向上,
Input
第一行一个整数t,表示t组样例,
接下来t组样例
每组样例 第一行两个数 n,m n小于100 ,m小于100
接下来m行 每行四个数 x1,x2,y1,y2 表示电梯停靠楼层 x1<x2<y1<y2
Output
每组样例输出一个整数 表示方法数 (结果对1e9+7取模)
Sample Input 1
2 5 2 1 1 3 3 2 3 5 5 5 1 1 1 2 5
Sample Output 1
1 8
Hint
note: 从一楼坐电梯直接到三楼,和坐这部电梯先到二楼下电梯再上这部电梯最终到达三楼,被考虑为是不同的方案
题目分析 : 有 m 个长度为 n 的电梯,不同电梯可以停靠的楼层不同,就是一个递推式的 dp, 首先比如对于第 3 层来学,总的方案数就是到第一层的方案数乘以 第一层到第三层的方案总数 + 第二层到第三层的方案数
代码示例 :
#define ll long long const ll eps = 1e9+7; int n, m; int mp[105][105]; ll dp[105]; ll f[105]; int main() { freopen("1.in", "r", stdin); int t; int x1, y1, x2, y2; cin >> t; while(t--){ scanf("%d%d", &n, &m); memset(mp, 0, sizeof(mp)); int sign = 0; for(int i = 1; i <= m; i++){ scanf("%d%d%d%d", &x1, &y1, &x2, &y2); for(int j = x1; j <= y1; j++){ mp[i][j] = 1; if (j == 1) sign = 1; } for(int j = x2; j <= y2; j++){ mp[i][j] = 1; if (j == 1) sign = 1; } } memset(dp, 0, sizeof(dp)); if (sign) dp[1] = 1ll; else { printf("0\n"); continue; } for(int i = 2; i <= n; i++){ for(int j = i-1; j >= 1; j--){ ll cnt = 0; for(int k = 1; k <= m; k++){ if (mp[k][i] && mp[k][j]) cnt++; } dp[i] += ((dp[j]%eps)*(cnt%eps))%eps; dp[i] %= eps; } } printf("%lld\n", dp[n]%eps); } return 0; }
东北日出西边雨 道是无情却有情