CF14E Camels (思维,DP)
思路: 以数组下标为横坐标,数组值为纵坐标建立直角坐标系。 根据题意,该数组在坐标上的图像是开始先递增的折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;
}