状态很好想,表示考虑到第k个音符,左手在
右手在
的最小花费。转移也非常简单。
每次转移的时候只需要枚举该音符的左右9个位置就行了。同时判断一下该音符是否已被另一只手占据,如果是则应不考虑用这只手弹那个音。(然而不判断似乎也能过?不太清楚了)
复杂度
#include<cstdio>
#include<math.h>
#include<iostream>
using namespace std;
#define pb push_back
#define fi first
#define se second
#define ll long long
#define pq priority_queue
#define mp make_pair
#define pii pair<int,int>
#define mod 998244353
#define debug(x) cerr<<#x<<"="<<x<<'\n'
int lowbit(int x) {return x&(-x);}
int L,R,n;
int f[1010][55][55];
int a[1010];
const int INF=1e9;
int tmp[101];
void init() {
for (int i=0;i<10;i++) {
for (int j=i*i;j<(i+1)*(i+1);j++) tmp[j]=i;
}
}
int ABS(int x) {
if (x<0) return -x;
return x;
}
void solve() {
for (int i=0;i<1010;i++)
for (int j=0;j<52;j++)
for (int k=0;k<52;k++) f[i][j][k]=INF;
f[0][L][R]=0;
for (int i=0;i<n;i++) {
int cur;
scanf("%d",&cur);
for (int l=0;l<52;l++)
for (int r=0;r<52;r++) {
if (f[i][l][r]==INF) continue;
//l
if (cur<r||cur>=r+5) {
for (int j=cur;j<cur+9&&j<52;j++)
f[i+1][j][r]=min(f[i+1][j][r],f[i][l][r]+tmp[ABS(l-j)]);
}
//r
if (cur>l||cur<=l-5) {
for (int j=cur;j>=0&&j>cur-9;j--)
f[i+1][l][j]=min(f[i+1][l][j],f[i][l][r]+tmp[ABS(r-j)]);
}
}
}
int ans=INF;
for (int i=0;i<52;i++)
for (int j=0;j<52;j++) ans=min(ans,f[n][i][j]);
cout<<ans<<endl;
}
int main(){
init();
while (scanf("%d%d%d",&L,&R,&n)!=EOF) solve();
return 0;
}