A. King Moves
思路
根据棋盘的特点可以分类讨论:
- 当王在棋盘的角落上时,王有 3 种走法。
- 当王在棋盘的边缘上时,王有
5 种走法。 - 其它情况,王有 8 种走法
代码
#include <bits/stdc++.h>
using namespace std;
string s;
int main() {
cin >> s;
if(s == "a1" || s == "h1" || s == "a8" || s == "h8") {
cout << 3;
}
else if(s[0] == 'a' || s[0] == 'h' || s[1] == '1' || s[1] == '8') {
cout << 5;
}
else {
cout << 8;
}
cout << endl;
return 0;
}
B. Optimal Point on a Line
思路
朴素的思想中,枚举最优点,然后计算所有点到这个点的距离之和就能解决问题。但是
接下来考虑让点有序是否对解题会有帮助,假设现在的点是按照坐标的大小从小到大排列的。考虑当我们知道了第
i
个点到所有点的距离之和
于是在算出了 sum(i) ,以后,我们就可以根据 sub(i) 求得 sum(i+1) ,从而从 sum(1) 递推到 sum(n) 。问题就在 O(n) 的复杂度下圆满地解决了。
代码
#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
const int maxn = 3e5 + 5;
int n, x;
ll sum, ans, a[maxn];
int main() {
scanf("%d", &n);
for(int i = 1; i <= n; i++) {
scanf("%I64d", &a[i]);
}
sort(a + 1, a + n + 1);
for(int i = 2; i <= n; i++) {
sum += a[i] - a[1];
}
ans = sum;
x = a[1];
for(int i = 2; i <= n; i++) {
sum += (i + i - n - 2) * (a[i] - a[i-1]);
if(sum < ans) {
ans = sum;
x = a[i];
}
}
printf("%d\n", x);
return 0;
}
C. Magic Odd Square
思路
奇数阶幻方的幻和恰好也是奇数,于是问题就转化成了如何构造奇数阶幻方。(关于幻方,幻和和奇数阶幻方的构造,进入这个链接了解更多)
代码
#include <bits/stdc++.h>
using namespace std;
const int maxn = 50;
int n, x, y, tx, ty, G[maxn][maxn];
int main() {
scanf("%d", &n);
x = 0;
y = n / 2;
for(int i = 1; i <= n * n; i++) {
G[x][y] = i;
tx = (x - 1 + n) % n;
ty = (y + 1) % n;
if(G[tx][ty] > 0) {
x++;
continue;
}
x = tx;
y = ty;
}
for(int i = 0; i < n; i++) {
for(int j = 0; j < n; j++) {
printf("%d ", G[i][j]);
}
puts("");
}
return 0;
}
E. Generate a String
思路
原本的思路是,因为状态
i
(生成
下面说明正确的解法:
- 当
i
为奇数时,状态
i 从状态 i−1 或 i+12 转移过来是最优的。为什么是 i+12 而不是 i+32 或者数值更大的状态呢?因为从 i+32 转移过来不如先从 i+32 转移到 i+32−1 再转移到 2×(i+32−1) ,即 i+1 ,这样转移到 i 的花费会更少。最后状态转移方程就是d[i]=min(d[i−1]+x,d[(i+1)/2]+x+y) 。 - 当
i
为偶数时,状态
i 从状态 i−1 或 i2 转移过来是最优的。为什么是 i2 而不是 i+22 或数值更大的状态呢?答案跟奇数的情形是类似的,这里就不赘述了。最后状态转移方程就是 d[i]=min(d[i−1]+x,d[i/2]+y) 。
代码
#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
const int maxn = 1e7 + 5;
int n, x, y;
ll d[maxn];
int main() {
cin >> n >> x >> y;
for(int i = 1; i <= n; i++) {
if(i % 2) {
d[i] = min(d[i-1] + x, d[(i+1)/2] + x + y);
}
else {
d[i] = min(d[i-1] + x, d[i/2] + y);
}
}
cout << d[n] << endl;
return 0;
}
(其它题目略)