Wooden Signs dp

来源:互联网 发布:windows 文件管理工具 编辑:程序博客网 时间:2024/05/17 23:32

题目链接

题意:

木匠要做N个路标并把它们钉在一起(如图).
每个路标可以朝左也可以朝右,但是每个路标的起点要跟下一层路标的起点或终点重合. 重合位置必须有面积覆盖,不能像231

右图那种只重合一个点.
现在他不记得这些路标各自的朝向了. 但是他记得N+1个值,其中第1个值是第1个路标的终点坐标. 其余为n块的起点,(这里以箭头为头)
求可能满足条件的路标有多少种情况. (区别在于各自的朝向)(第一块路标一定朝右)

思路:

dp[i][j] 表示第i块木头 终点在j的方案数。

那么我们就可以分三种情况讨论,一种是头部在尾部的右边,一种是在左边,还有是在中间.在中间的时候有两种情况.

#include<bits/stdc++.h>#define inf 0x3f3f3f3f#define mod 2147483647using namespace std;typedef long long ll;const int maxn=2222;ll dp[maxn][maxn],a[maxn];int n,start;int main(){memset(dp,0,sizeof(dp));scanf("%d",&n);scanf("%d",&start);for(int i=1;i<=n;i++)scanf("%lld",&a[i]);dp[1][start]=1;for(int i=2;i<=n;i++){for(int j=1;j<=n+1;j++){if(dp[i-1][j]!=0){int st=a[i-1],en=j;if(st>en)swap(st,en);//cout<<st<<' '<<en<<endl;if(a[i]<=st){ dp[i][en]=(dp[i][en]+dp[i-1][j])%mod;}else if(a[i]>=en){  dp[i][st]=(dp[i][st]+dp[i-1][j])%mod;}else{dp[i][en]=(dp[i][en]+dp[i-1][j])%mod;dp[i][st]=(dp[i][st]+dp[i-1][j])%mod;//cout<<3<<endl;}}}}/*for(int i=1;i<=n+1;i++)cout<<dp[n][i]<<endl;*/ll ans=0;for(int i=1;i<=n+1;i++){ans=(ans+dp[n][i])%mod;}printf("%lld\n",ans); return 0;}


0 0