首页 > 代码库 > dp+分类讨论 Gym 101128E
dp+分类讨论 Gym 101128E
题目链接:http://codeforces.com/gym/101128
感觉这个人写的不错的(我只看了题目大意):http://blog.csdn.net/v5zsq/article/details/61428924
Description
n个小木条,一段前面有一个小箭头,给出第一个小木条的非箭头端端点横坐标以及每个小木条箭头端的坐标,现在要从下往上把这n’个木条按顺序叠放好,要求相邻两个小木条必须有一个共同端点且有交叠部分,问小木条有多少种放法
Input
第一行一整数n表示木条数量,之后输入n+1个整数分别表示第一个小木条非箭头端点和n个小木条的箭头端点横坐标(1<=n < 2000,每个端点横坐标是一个介于1~n+1之间的整数,保证第一个小箭头朝右)
思路:
定义dp(i,j)表示目前是第i个木头,他的区间是[min(j, a[i]), max(j, a[i])].
然后我们判断一下a[i-1]的范围和这个区间的范围,即分类讨论五种。
然后为了维护其中两种,所以我们这里还用了一个sum[j]数组表示dp[i][0]~dp[i][j]的和,然后这样就可以O(1)的到了
注意特判n=1的时候(因为这个wa了一发)
复杂度O(n^2)
//看看会不会爆int!数组会不会少了一维! //取物问题一定要小心先手胜利的条件 #include <bits/stdc++.h> using namespace std; #pragma comment(linker,"/STACK:102400000,102400000") #define LL long long #define ALL(a) a.begin(), a.end() #define pb push_back #define mk make_pair #define fi first #define se second #define haha printf("haha\n") const int maxn = 2000 + 5; const LL mod = 2147483647; LL dp[maxn][maxn]; LL sum[maxn]; int a[maxn]; int n; int main(){ while(scanf("%d", &n) == 1){ for (int i = 0; i <= n; i++){ scanf("%d", a + i); } if (n == 1) { printf("1\n"); continue; } memset(dp, 0, sizeof(dp)); memset(sum, 0, sizeof(sum)); for (int i = 1; i <= n + 1; i++){ if (i == a[0] || i == a[1]) sum[i] = dp[1][i] = 1; sum[i] = 1; } int len = n + 1; for (int i = 2; i <= n; i++){ for (int j = 1; j <= len; j++){ if (j == a[i]) continue; int lb = min(j, a[i]), rb = max(j, a[i]); //printf("lb = %d rb = %d\n", lb, rb); if (a[i - 1] < lb){ dp[i][j] += dp[i - 1][rb]; } else if (a[i - 1] == lb){ dp[i][j] += (sum[len] - sum[lb] + mod) % mod; } else if (a[i - 1] > rb){ dp[i][j] += dp[i - 1][lb]; } else if (a[i - 1] == rb){ dp[i][j] += sum[rb - 1]; } else { dp[i][j] += dp[i - 1][lb] + dp[i - 1][rb]; } if (dp[i][j] >= mod) dp[i][j] %= mod; //printf("dp[%d][%d] = %lld\n", i, j, dp[i][j]); } for (int j = 1; j <= len; j++){ sum[j] = (sum[j - 1] + dp[i][j]) % mod; } } LL ans = 0; for (int i = 1; i <= len; i++){ ans = (ans + dp[n][i]) % mod; } cout << ans << endl; } return 0; }
dp+分类讨论 Gym 101128E
声明:以上内容来自用户投稿及互联网公开渠道收集整理发布,本网站不拥有所有权,未作人工编辑处理,也不承担相关法律责任,若内容有误或涉及侵权可进行投诉: 投诉/举报 工作人员会在5个工作日内联系你,一经查实,本站将立刻删除涉嫌侵权内容。