USACO白金題目 Subsequence Reversal (range DP / 剪枝 / 記憶化收索)
#include <bits/stdc++.h>
using namespace std;
const int MAX=51;
int d[MAX][MAX][MAX][MAX],a[MAX],n;
int dfs(int l, int r,? int lmx, int rmn){
? ? if(lmx>rmn){
? ? ? ? return -MAX;
? ? }
? ? if(l>r){
? ? ? ? return 0;
? ? }
? ? if(d[l][r][lmx][rmn]!=-1){//restore
? ? ? ? return d[l][r][lmx][rmn];
? ? }
? ? int res=0;
? ? res=max(res,dfs(l+1, r,lmx,rmn));//左邊不選
? ? res=max(res,dfs(l, r-1,lmx,rmn));//右邊不選
? ? if(a[l]>=lmx){
? ? ? ? res=max(res,dfs(l+1,r,a[l],rmn)+1);//選左邊
? ? }? ??
? ? if(a[r]<=rmn){
? ? ? ? res=max(res,dfs(l,r-1,lmx,a[r])+1);//選右邊
? ? }
? ? if(a[r]>=lmx && r-l>0){
? ? ? ? res=max(res,dfs(l+1,r-1,a[r],rmn)+1);//交換,選左邊,不選右邊,不動(dòng)a數(shù)組
? ? }? ??
? ? if(a[l]<=rmn && r-l>0){
? ? ? ? res=max(res,dfs(l+1,r-1,lmx,a[l])+1);//交換,選右邊,不選左邊,不動(dòng)a數(shù)組
? ? }
? ? if(a[l]<=rmn && a[r]>=lmx && r-l>0){//交換,選兩邊,不動(dòng)a數(shù)組
? ? ? ? res=max(res,dfs(l+1,r-1,a[r],a[l])+2);
? ? }
? ? d[l][r][lmx][rmn]=res;//記憶化搜索
? ? return res;
}? ??
? ??
int main(){
? ? ifstream fin("subrev.in");
? ? ofstream fout("subrev.out");
? ? fin>>n;
? ? for(int i=1;i<=n;i++){
? ? ? ? fin>>a[i];
? ? }
? ? memset(d,-1,sizeof(d));
? ? fout<<dfs(1,n,0,50);
? ? return 0;
}