CF14E Camels (思维,DP)

image

思路: 以数组下标为横坐标,数组值为纵坐标建立直角坐标系。 根据题意,该数组在坐标上的图像是开始先递增的折2* t-1次的折线。
可是设dp数组f[i][j][y]表示到第i个数,折了j次,且第i个数为y的方案数目。因为开头必递增,所以可以根据j的奇偶性来转移:
若当前折了偶数次,那么i之前是递减的,a[i] > a[i - 1]就会新增一个折, a[i] < a[i - 1] 折不变,奇数次相反。

if( j % 2 == 0 ) {
           if( h < y ) f[i][j][y] += f[i - 1][j][h];
           if( h > y  ) f[i][j + 1][y] += f[i - 1][j][h];//**
         }

注意: **处不能写成:if( h > y && j >= 1 ) f[i][j][y] += f[i - 1][j - 1][h]; 这样转移破坏了j的奇偶性

#include<bits/stdc++.h>
using namespace std;
#define IOS ios::sync_with_stdio(false) ,cin.tie(0), cout.tie(0);
//#pragma GCC optimize(3,"Ofast","inline")
#define ll long long
#define PII pair<int, char>
//#define int long long
const int N = 3e5 + 5;
const int M = 1e5 + 5;
const int INF = 0x3f3f3f3f;
const ll LNF = 0x3f3f3f3f3f3f3f3f;
const int mod = 998244353;
const double PI = acos(-1.0);
ll f[25][25][5];
int main () {
  ios::sync_with_stdio(false), cin.tie(0), cout.tie(0);
  int n, t; cin >> n >> t;
  for ( int i = 1; i <= 3; ++ i ) f[1][0][i] = 1;
  for ( int i = 2; i <= n; ++ i ) {
    for ( int j = 0; j <= t * 2 - 1; ++ j ) {
      for ( int y = 1; y <= 4; ++ y) {
        for ( int h = 1; h <= 4; ++ h ) {
          if( i == 2 ) {
            if( h < y ) {
              if( j == 0 )f[i][j][y] += f[i - 1][j][h];
            }
            continue;
          }
          
          if( j % 2 == 0 ) {
            if( h < y ) f[i][j][y] += f[i - 1][j][h];
            if( h > y  ) f[i][j + 1][y] += f[i - 1][j][h];
          } else {
            if( h > y ) f[i][j][y] += f[i - 1][j][h];
            if( h < y  ) f[i][j + 1][y] += f[i - 1][j][h];
          }

        }
      }
    }
  }
  ll ans = 0;
  for ( int i = 1; i <= 4; ++ i ) ans += f[n][t * 2 - 1][i];
  cout << ans << '\n';
  return 0;
}
posted @ 2022-06-22 20:56  qingyanng  阅读(22)  评论(0编辑  收藏  举报