CodeForces 567F DP Mausoleum

  1 #include <iostream>
  2 #include <cstdio>
  3 #include <cstring>
  4 #include <algorithm>
  5 #include <vector>
  6 #include <map>
  7 #define MP make_pair
  8 using namespace std;
  9
 10 typedef long long LL;
 11
 12 const int maxn = 80;
 13
 14 int n, k;
 15
 16 vector<int> G[maxn], req[maxn];
 17
 18 LL d[maxn][maxn];
 19
 20 bool check(int L, int R, int l, int r)
 21 {
 22     for(int i = 0; i < G[l].size(); i++)
 23     {
 24         int v = G[l][i], t = req[l][i];
 25         if(t == -2)
 26         {
 27             if(v < L || v > R || v == r) return false;
 28         }
 29         else if(t == -1)
 30         {
 31             if(v < L || v > R) return false;
 32         }
 33         else if(!t)
 34         {
 35             if(v != r) return false;
 36         }
 37         else if(t == 1)
 38         {
 39             if(v >= L && v <= R && v != r) return false;
 40         }
 41         else
 42         {
 43             if(v >= L && v <= R) return false;
 44         }
 45     }
 46
 47     for(int i = 0; i < G[r].size(); i++)
 48     {
 49         int v = G[r][i], t = req[r][i];
 50         if(t == -2)
 51         {
 52             if(v < L || v > R || v == l) return false;
 53         }
 54         else if(t == -1)
 55         {
 56             if(v < L || v > R) return false;
 57         }
 58         else if(!t)
 59         {
 60             if(v != l) return false;
 61         }
 62         else if(t == 1)
 63         {
 64             if(v >= L && v <= R && v != l) return false;
 65         }
 66         else
 67         {
 68             if(v >= L && v <= R) return false;
 69         }
 70     }
 71
 72     return true;
 73 }
 74
 75 LL dp(int L, int R)
 76 {
 77     LL& ans = d[L][R];
 78     if(ans >= 0) return d[L][R];
 79     if(L + 1 == R)
 80     {
 81         if(check(L, R, L, R)) return 1LL;
 82         return 0;
 83     }
 84
 85     ans = 0;
 86
 87     if(check(L, R, L, L + 1))
 88         ans += dp(L + 2, R);
 89     if(check(L, R, L, R))
 90         ans += dp(L + 1, R - 1);
 91     if(check(L, R, R - 1, R))
 92         ans += dp(L, R - 2);
 93
 94     return ans;
 95 }
 96
 97 int main()
 98 {
 99     scanf("%d%d", &n, &k);
100     char eq[10];
101     while(k--)
102     {
103         int u, v;
104         scanf("%d", &u);
105         scanf("%s", eq);
106         scanf("%d", &v);
107
108         int t;
109         if(strcmp(eq, "<") == 0) t = -2;
110         else if(strcmp(eq, "<=") == 0) t = -1;
111         else if(strcmp(eq, "=") == 0) t = 0;
112         else if(strcmp(eq, ">=") == 0) t = 1;
113         else if(strcmp(eq, ">") == 0) t = 2;
114         else exit(1234);
115
116         if(u == v)
117         {
118             if(abs(t) <= 1) continue;
119             else { puts("0"); exit(0); }
120         }
121
122         req[u].push_back(t); req[v].push_back(-t);
123         G[u].push_back(v); G[v].push_back(u);
124     }
125
126     memset(d, -1, sizeof(d));
127
128     printf("%I64d\n", dp(1, n * 2));
129
130     return 0;
131 }

代码君

时间: 2024-10-15 15:53:32

CodeForces 567F DP Mausoleum的相关文章

【CodeForces 567F】Mausoleum

寒假最后一题补完啦 ^∀^ 题意 1到n每个数字有两个,排成先不降后不升的序列,比如112332,并且满足k个形如 3 <= 6 代表第三个数字要≤第六个数字这样的约束要求,求有多少种排法. 分析 区间DP,dp[i][j]表示只有区间[i,j]还没填时的方案数. b[i][j]表示第i和j位置的数字约束关系. 然后从两头开始排,每次把两个数字t放在两边或者同一边. dp[i+1][j-1]+=dp[i][j];//放在两边 dp[i+2][j]+=dp[i][j];//放在左边 dp[i][j

codeforces 449D DP+容斥

Jzzhu and Numbers Time Limit:2000MS     Memory Limit:262144KB     64bit IO Format:%I64d & %I64u Submit Status Appoint description:  System Crawler  (2014-07-20) Description Jzzhu have n non-negative integers a1, a2, ..., an. We will call a sequence o

Codeforces 567F Mausoleum dp

Mausoleum 考虑将数字从大到小一种一种填进去, 新加入的数字只会在之前组成序列的两侧, 所以形状一直是连续的一段. dp[ k ][ i ][ j ] 表示填入了前 k 大的数字, 它们位于i - j 的合法方案数, 转移的时候check一下能否转移. #include<bits/stdc++.h> #define LL long long #define LD long double #define ull unsigned long long #define fi first #d

codeforces 567F mausoleum

http://codeforces.com/problemset/problem/567/F dp 没有想出来,感觉这题还是比较有意思. 题意: 有n个数,要求放置.每个数要放置两次.要求最后整个序列的顺序是先不减后不增.还给出了k个限制条件.求满足这些条件的序列的总数. 思路: 还是比较容易想到是用dp做的.就是不知道怎么转移状态...orz 因为小的数字总是要在大的数字的两边的,可以考虑同时放置两个数值相同的数字,此时有三种放置的情况.1)将这两个数字放在序列的两旁.2)都放在序列的前面.3

CodeForces 706C dp

C - Hard problem Time Limit:1000MS     Memory Limit:262144KB     64bit IO Format:%I64d & %I64u Submit Status Practice CodeForces 706C Description Vasiliy is fond of solving different tasks. Today he found one he wasn't able to solve himself, so he as

codeforces的dp专题

1.(467C)http://codeforces.com/problemset/problem/467/C 题意:有一个长为n的序列,选取k个长度为m的子序列(子序列中不能有位置重复),求所取的k个序列求和的最大值是多少 分析:设dp[i][j]在[j,n]范围内取了i个子序列求和所得的最大值,用sum[i]表示[1,i]的求和.转移方程为dp[i][j]=max(dp[i-1][j+m]+sum[j+m-1]-sum[j-1],dp[i][j+1]),表示要不要选择[j,j+m-1]这段为其

codeforces 711C dp

一眼dp,但是这道题不知怎么搞遇到点小问题,又搞了搞才出来,就是给你一些颜色.这个点有颜色,不能图,反之可以.问形成k段连续颜色的最小花费. 纯纯的dp,不知道为什么就是有问题...终于借鉴了别人的A过了,后面再研究吧. #include <cstdio> #include <cstring> #include <vector> #include <cmath> #include <stack> #include <cstdlib>

Codeforces 404D [DP]

/* 我是一个习惯后悔,但是没办法忍受内疚感的二货== 这题是个无脑dp,但是比赛大概20min没出...其实最后5min我好好想想简单化边界条件,可以出的. 题意: 给你一个长度为1e6的由?*01四种字符组成的字符串,类似扫雷,?代表当前不确定,0代表当前无雷,并且 两边无雷,1代表当前五雷且两边有一个雷,2同样的,问当所有格子已知以后一共有多少种可能的局面. 思路: 首先想到的是,这个问题无后效性,而当前位置的合法方式只与它之前的两位有关. 所以dp的思路也是显而易见的,即dp[i][j]

codeforces 608C:(dp)

从又往左点灯塔,点亮一个的同时,往左di范围内的灯塔全部被破坏.现在能在最右端按一个灯塔,攻击范围任意,问到最后最少有几个灯塔留下 用dp瞎搞.具体看代码吧 #include"cstdio" #include"queue" #include"cmath" #include"stack" #include"iostream" #include"algorithm" #include&quo