转移方程:
d
p
[
i
]
[
j
]
=
m
a
x
(
d
p
[
i
]
[
j
]
,
d
p
[
i
]
[
k
]
+
d
p
[
k
+
1
]
[
r
]
+
w
[
l
]
[
r
]
)
dp[i][j] = max(dp[i][j], dp[i][k] + dp[k+1][r] + w[l][r])
dp[i][j]=max(dp[i][j],dp[i][k]+dp[k+1][r]+w[l][r])
#include<bits/stdc++.h>usingnamespace std;typedeflonglong ll;#definerep(i, a, n)for(int i = a; i <= n; i++)#defineper(i, a, n)for(int i = n; i >= a; i--)#definelowbit(x)((x)&-(x))#definelsonp <<1, l, mid#definersonp <<1|1, mid +1, r#definemem(a, b)memset(a, b,sizeof(a))#defineIOS\ios::sync_with_stdio(false);\cin.tie(0);\cout.tie(0)/*
环形经典优化方式:将环拆分成长度为n的链,在将其后接入条长度为n的链
*/constint N =205;int a[N *2];int sum[N *2];int dp_max[N *2][N *2];int dp_min[N *2][N *2];int n;intmain(){
IOS;
cin >> n;for(int i =1; i <= n; i++){
cin >> a[i];
a[n + i]= a[i];}for(int i =1; i <= n *2; i++)
sum[i]= sum[i -1]+ a[i];memset(dp_max,-0x3f,sizeof(dp_max));memset(dp_min,0x3f,sizeof(dp_min));for(int len =1; len <= n; len++)//区间长度{for(int l =1; l + len -1<= n *2; l++)//枚举左端点{int r = l + len -1;if(len ==1)
dp_max[l][r]= dp_min[l][r]=0;else{for(int k = l; k < r; k++)//枚举分界点{
dp_min[l][r]=min(dp_min[l][k]+ dp_min[k +1][r]+ sum[r]- sum[l -1], dp_min[l][r]);
dp_max[l][r]=max(dp_max[l][k]+ dp_max[k +1][r]+ sum[r]- sum[l -1], dp_max[l][r]);}}}}int ans_max =0, ans_min = INT_MAX;for(int l =1; l + n -1<= n *2; l++){int r = l + n -1;
ans_max =max(ans_max, dp_max[l][r]);
ans_min =min(ans_min, dp_min[l][r]);}
cout << ans_min <<"\n"<< ans_max;return0;}
二、数位DP
数位dp经典思想
一般的问题描述为:
给的区间
[
x
,
y
]
[x,y]
[x,y],让你找到符合一定性质数的个数。
在区间中,满足性质
[
x
,
y
]
−
>
d
p
[
y
]
−
d
p
[
x
−
1
]
[x,y]->dp[y]-dp[x-1]
[x,y]−>dp[y]−dp[x−1]
#include<bits/stdc++.h>usingnamespace std;typedeflonglong ll;#defineIOS\ios::sync_with_stdio(false);\cin.tie(0);\cout.tie(0)constint N =15;
ll f[N][12];voidinit()// f[i][j]表示前i位,当前位为j的windy数的个数{for(int i =1; i <=9; i++)
f[1][i]=1;for(int i =2; i < N; i++){for(int j =0; j <=9; j++){for(int k =0; k <=9; k++){if(abs(j - k)>=2)
f[i][j]+= f[i -1][k];}}}}
ll dp(int x){if(x ==0)return0;
vector<int> ve;while(x)
ve.push_back(x %10), x /=10;
ll res =0;int len = ve.size();int last =999;for(int i = len -1; i >=0; i--){int num = ve[i];for(int j =(i == len -1); j < num; j++)//不处理前导0{if(abs(last - j)>=2)
res += f[i +1][j];}if(abs(last - num)<2)break;
last = num;if(!i)
res++;}for(int i =1; i < len; i++)//处理有前导0,第i+1位是0{for(int j =1; j <=9; j++){
res += f[i][j];}}return res;}intmain(){
IOS;init();int l, r;
cin >> l >> r;
cout <<dp(r)-dp(l -1);return0;}