有一把锁从左到右有n个数,组成了一个序列。只要将锁设置为输入任意单峰序列即可打开。具体为:a_1 \le \cdots \le a_i \ge a_{i+1} \ge \cdots \ge a_n\quad (1 \le i \le n)a 1 ≤⋯≤a i ≥a i+1≥⋯≥a n(1≤i≤n)。锁是拨动式的即拨一下就能换成临近的一个数(0和9可以互换求最少拨几下可以开锁。 c++代码
时间: 2024-03-23 10:38:18 浏览: 84
这是一道经典的动态规划问题,可以使用类似于LIS(最长上升子序列)的思路解决。设dp[i][j]表示将前i个数变为单峰序列,且最后一个数为j的最小操作次数。则有转移方程:
dp[i][j] = min(dp[i-1][k] + abs(j-a[i])) (k<j)
其中abs(j-a[i])表示将第i个数变为j的操作次数。最终的答案为min(dp[n][j]),其中j为所有序列中的峰值。
以下是C++代码实现:
```c++
#include <iostream>
#include <cstring>
#include <algorithm>
using namespace std;
const int N = 1010;
int a[N];
int dp[N][10];
int main()
{
int n;
cin >> n;
for (int i = 1; i <= n; i ++ ) cin >> a[i];
memset(dp, 0x3f, sizeof dp);
for (int i = 0; i <= 9; i ++ )
dp[1][i] = abs(a[1] - i);
for (int i = 2; i <= n; i ++ )
for (int j = 0; j <= 9; j ++ )
for (int k = 0; k < j; k ++ )
dp[i][j] = min(dp[i][j], dp[i-1][k] + abs(a[i]-j));
int res = 0x3f3f3f3f;
for (int i = 0; i <= 9; i ++ )
for (int j = i+1; j <= 9; j ++ )
res = min(res, dp[n][i] + dp[n][j]);
cout << res << endl;
return 0;
}
```
阅读全文