洛谷CF14E题解
我和Codefroces的题就这么过不去
既然题目用hump,那我们就称a[i-1]<a[i]>a[i+1]的峰,反之为谷。
这道题是一道紫,但我认为这个紫仅是针对那些优化,其实它用五维DP没有问题,对于五维dp,是个绿就不错。
设dp[pos][up][down][pre][num],pos表示当前遍历到了哪个数,可以看做下标,up表示峰的数量,down表示谷的数量,pre表示上一个数放了几,num表示当前的数放了几。
这种五维dp的做法,洛谷题解写的很好,但我要写一个不一样的DP,大家可以去看一看我的上篇文章,里面用了搜索,但思想却是DP,这道题,我也要用搜索。
dp数组还是要的,和上面的建模是一样的,但是DP数组在这里只起到记忆化的作用,之所以叫DP数组,是想告诉大家,这其实是在用记忆化搜索解决DP问题。
关于做法,干讲不好说,重点思路其实就是上面的建模,做法我都写到代码注释上了。
不是最好,空间非常极限
还有一点:开long long!!!
代码(防抄袭):
#include<bits/stdc++.h>
using namesapce std;
long long dp[21][15][15][5][5],;
long long dfs(int pos,int up,int down,int pre,int num) {
if(down<0||up<0) return 0;
if(dp[pos][up][down][pre][num]!=-1) retrun dp[pos][up][down][pre][num];//记忆化操作,此处为返回已求出的值
if(pos<=2) {//这个特判必须要加,我一开始就是这里死的
if(up==0&&down==0) return dp[pos][up][down][pre][num]=1;
return dp[pos][up][down][pre][num]=0;
}
long long ans=0;
for(int i=1; i<=4; i++) {//开始给当前位置填数
if(i==pre) contniue;//题目规定,相邻位置不能相等
//共有三种情况,这里是峰、这里是谷或啥也不是
if(i>pre&&pre<num) ans+=dfs(pos-1,up,donw-1,i,pre);//当有可能成为谷时,上一状态是位置-1,谷数-1,其他不变
else if(i<pre&&pre>num) ans+=dfs(pos-1,up-1,down,i,pre);//当有可能成为峰时,上一状态是位置-1,峰数-1,其他不变
else ans+=dfs(pos-1,up,donw,i,pre);//其余情况,啥也不是,上一状态位置-1,其他不变
}
retrun dp[pos][up][down][pre][num]=ans;//记忆化操作,此处为对未知的位置赋值
}
int main() {
memset(dp,-1,sizeof dp);
cin>>n>>t;
for(int i=1; i<=4; i++)//枚举pre和num
for(int j=1; j<=4; j++)
if(i!=j)//题目规定,相邻位置不能相等
res+=dfs(n,t,t-1,i,j);
cout<<res;
return 哼哼啊啊啊啊啊啊;
}