1. 題目一


首先將數據排序,則兩端的點距離最遠肯定要舍棄一個,訪問 \(n-1\) 個點只有兩種情況,\(x_1 \to x_{n-1} 或者 x_2 \to x_{n}\)。假設訪問的點是 \(x_2 \to x_{n}\),則又有下圖兩種訪問順序,先右后左或者先左后右,距離分別為 \(dis1 = 2 * (x_n - a) + (a - x_2)\) 和 \(dis2 = 2 * (a - x_2) + (x_n - a)\)。

因此,共計四個距離,選取最小的一個即可。
#include <iostream>
#include<vector>
#include<stdio.h>
#include<limits.h>
#include<algorithm>
using namespace std;
int main()
{
int n = 0;
int a = 0;
scanf("%d %d", &n, &a);
vector<int> pos;
for(int i = 0; i < n; i++)
{
int temp;
scanf("%d", &temp);
pos.push_back(temp);
}
sort(pos.begin(), pos.end());
// 0 到 n-2 先左后右
int dis1 = 2 * abs(a - pos[0]) + abs(pos[n-2] - a);
// 0 到 n-2 先右后左
int dis2 = abs(a - pos[0]) + 2 * abs(pos[n-2] - a);
// 1 到 n-1 先左后右
int dis3 = 2 * abs(a - pos[1]) + abs(pos[n-1] - a);
// 1 到 n-1 先右后左
int dis4 = abs(a - pos[1]) + 2 * abs(pos[n-1] - a);
int result = INT_MAX;
result = min(result, dis1);
result = min(result, dis2);
result = min(result, dis3);
result = min(result, dis4);
cout << result << endl;
return 0;
}
2. 題目二


我們假設爬到第 \(i\) 層需要的最少時間為 \(S[i]\),那么我們有三種情況可以做到。
第一,從 \(i-2\) 層跳兩層過來,根據題意,跳之前我們肯定爬過了一層(不可能連續跳兩次),也就是從第 \(i-3\) 層爬到了第 \(i-2\) 層,然后再跳到第 \(i\) 層,這時候,需要的時間即為 \(S[i] = S[i-3]+data[i-3]\),注意此處,\(data[i-3]\)是數組的第 \(i-2\) 個元素,代表第 \(i-2\) 層的高度。
第二,從 \(i-1\) 層跳一層過來,也就是從第 \(i-2\) 層爬到了第 \(i-1\) 層,然后再跳到第 \(i\) 層,這時候,需要的時間即為 \(S[i] = S[i-2]+data[i-2]\)。
第三,從 \(i-1\) 層直接爬到第 \(i\) 層,這時候,\(S[i] = S[i-1]+data[i-1]\)。

所以,\(S[i]\) 即為以上三種情況的最小值。
#include <iostream>
#include <stdio.h>
#include <string>
#include <algorithm>
using namespace std;
int main()
{
int result = 0;
int n;
scanf("%d", &n);
int data[n];
for(int i = 0;i < n; i++) scanf("%d", &data[i]);
int dp[n+1];
dp[0] = 0;
dp[1] = 0;
dp[2] = 0;
for (int i = 3; i < n + 1; ++i)
{
dp[i] = min(min(dp[i-3] + data[i-3], dp[i-2] + data[i-2]),dp[i-1] + data[i-1]);
}
cout << dp[n];
return 0;
}
3. 題目三


借助隊列來實現即可。
#include <iostream>
#include <queue>
using namespace std;
int main()
{
int n = 0;
scanf("%d", &n);
queue<int> q;
for (int i = 1; i <= n; i++) q.push(i);
while (q.size() != 1)
{
printf("%d ", q.front());
q.pop();
q.push(q.front());
q.pop();
}
printf("%d", q.front());
return 0;
}
4. 題目四
待定
5. 題目五
小 Q 得到了一個長度為 \(n\) 的序列 \(A\),\(A\) 中的數各不相同。對於 \(A\) 中的每一個數 \(A_i(2\leqslant i\leqslant n)\) ,求 \(min|A_i-A_j|, j < i\) 以及令上式取得最小值的下標 \(j\) 。若最小值點不唯一,則選擇較小的那個。
假設 \(A[j]\) 和 \(A[i]\) 的絕對值最小,則 \(A[i]\) 左邊其余的數據分布在大括號兩邊,如下圖所示。

- 若 \(A[j] \leqslant A[i+1] \leqslant A[i]\),則排除掉左右兩邊的點;
- 若 \(A[i+1] < A[j] \leqslant A[i]\),則排除掉右邊的點;
- 若 \(A[j] \leqslant A[i] < A[i+1]\),則排除掉左邊的點;

- 若 \(A[i] \leqslant A[i+1] \leqslant A[j]\),則排除掉左右兩邊的點;
- 若 \(A[i+1] < A[i] < A[j]\),則排除掉右邊的點;
- 若 \(A[i] < A[j] < A[i+1]\),則排除掉左邊的點;
#include <iostream>
#include <stdio.h>
#include <vector>
using namespace std;
int main()
{
int n;
scanf("%d", &n);
vector<int> num(n, 0);
for (int i = 0; i < n; i++)
{
scanf("%d", &num[i]);
}
int min_value[n][2];
min_value[1][0] = abs(num[1] - num[0]);
min_value[1][1] = 0;
for (int i = 2; i < n; i++)
{
int j = min_value[i-1][1];
int dis1 = abs(num[i] - num[j]);
int dis2 = abs(num[i] - num[i-1]);
int min_dis = min(dis1, dis2);
int index = dis1 <= dis2 ? j : i-1;
if ((num[i] <= num[j] && num[j] < num[i-1]) || (num[i] < num[i-1] && num[i-1] < num[j]))
{
int left = min(num[i-1], num[j]);
for (int k = 0; k < i - 1; k++)
{
if (num[k] < left)
{
int dis = abs(num[k] - num[i]);
if (dis < min_dis)
{
min_dis = dis;
index = k;
}
else if (dis == min_dis)
{
index = min(index, k);
}
}
}
}
else if ((num[j] <= num[i-1] && num[i-1] < num[i]) || (num[i-1] < num[j] && num[j] < num[i]))
{
int right = max(num[i-1], num[j]);
for (int k = 0; k < i - 1; k++)
{
if (num[k] > right)
{
int dis = abs(num[k] - num[i]);
if (dis < min_dis)
{
min_dis = dis;
index = k;
}
else if (dis == min_dis)
{
index = min(index, k);
}
}
}
}
min_value[i][0] = min_dis;
min_value[i][1] = index;
}
for (int i = 1; i < n; i++)
{
printf("%d %d\n", min_value[i][0], min_value[i][1]+1);
}
return 0;
}
獲取更多精彩,請關注「seniusen」!

