【学时总结】◆学时·VII◆ 高维DP

◆学时·VII◆ 高维DP

自学之余,偶遇DP……


◇ 算法概述

顾名思义——一种处理多方面状态的DP,这种DP特点是……每一维的大小都不算太大(不然用dp数组存储下来内存会炸),而且枚举时容易超时……(一般来说,DP的复杂度为每一维的可取值之积。毕竟是乘积,很容易炸掉)。

众所周知,除了状压DP,一般的DP都是每一维表示了一个方面的状态,因此我们需要按照一定顺序枚举状态。

高维DP的大多数题中,各个方面的状态是互相关联、影响的,因此注意状态之间的互相限制是高维DP的难点,这也导致高维DP非常费脑子——状态转移方式奇多无比。

还有什么注意事项就看下面的例题吧~


◇ 例题选讲

(好像只找到一道题,之后找到其他的好题再补上吧……QwQ)

【Codeforces 14E】Camels +传送门+

· 题目大意

n个数依次为A1~n,当且仅当第i个数(1<i<n)满足 Ai-1<Ai 且 Ai>Ai+1 ,我们称Ai是一个驼峰;当且仅当 Ai-1>A且 Ai<Ai+1 ,我们称 Ai 是一个谷底。已知 1≤Ai≤4 ,求恰好形成t个驼峰的方案数。

· 解析

这道题是DP没任何问题,统计类一般是DP(其他就是暴力DFS)……

现在就可以开始找有哪些方面的状态了:

数的位置 i;第 i 个位置上的数 j ;第 i 个数在第 k 个驼峰上(从上升段开始到下降段结束);第 i 个数在驼峰的上升/下降段。

注意:我们并不需要找到所有的状态,那些关联很紧密(几乎一一对应的)就不需要用了,我们只需要找相对有独立性但仍能影响其他状态的状态

有了这些状态,我们就可以进行状态转移了。

提示:如果你发现你找出的状态无法互相转移,不要犹豫,换一种方法吧……

分几种情况讨论(Tab. 这里将驼峰算作上升段,谷底算作下降段):

上升的第一种dp[i-1][r][k][1]就是i和i-1在同一个驼峰上且都处于上升段,直接相加;

上升的第二种dp[i-1][r][k-1][0]就是i-1是前一个驼峰上的下降段的末尾(谷底),直接相加;

下降的第一种dp[i-1][r][k][0]就是i-1和i在同一个驼峰上,都处于下降段,直接相加;

下降的第二种dp[i-1][r][k][1]就是i-1和i在同一个驼峰上,i-1处于上升段的末尾(驼峰),直接相加;

· 源代码

 1 /*Lucky_Glass*/
 2 #include<cstdio>
 3 #include<cstring>
 4 #include<algorithm>
 5 using namespace std;
 6 const int MAXN=20,MAXDIG=4,MAXT=10;
 7 typedef long long ll;
 8 ll dp[MAXN+5][MAXDIG+5][MAXT+5][2];
 9 //dp[i][j][k][r] 第i个数为j时在第k个驼峰上处于 r=1上升,r=0下降 状态
10 int main()
11 {
12     int n,t;scanf("%d%d",&n,&t);
13     dp[2][2][1][1]=1;
14     dp[2][3][1][1]=2;
15     dp[2][4][1][1]=3;
16     for(int i=3;i<=n;i++)
17         for(int j=1;j<=4;j++)
18             for(int k=1;k<=t;k++)
19                 for(int r=1;r<=4;r++) //上一个数字
20                 {
21                     if(r<j)
22                         dp[i][j][k][1]+=dp[i-1][r][k][1];
23                     if(r<j && k>0)
24                         dp[i][j][k][1]+=dp[i-1][r][k-1][0];
25                     if(r>j)
26                         dp[i][j][k][0]+=dp[i-1][r][k][0],
27                         dp[i][j][k][0]+=dp[i-1][r][k][1];
28                 }
29     ll ans=0;
30     for(int i=1;i<=4;i++)
31         ans+=dp[n][i][t][0];
32     printf("%lld\n",ans);
33     return 0;
34 }

 

The End

Thanks for reading!

- Lucky_Glass

(Tab:如果我有没讲清楚的地方可以直接在邮箱[email protected] email我,在周末我会尽量解答并完善博客~)

猜你喜欢

转载自www.cnblogs.com/LuckyGlass-blog/p/9445960.html
今日推荐