3831 地圖的密度
題意
點(x1,y1)與點(x2,y2)的距離爲max(|x1-x2|,|y1-y2|),求出與每個點距離不超過r的點(i,j),f[i,j]的總和。
思路
可以發現規律,距離是按一圈一圈增加的,所以我們可以用二維前綴和維護答案。
代碼
#include <cctype>
#include <cstdio>
int n, r;
int a[251][251], s[251][251];
inline int input() {
char c = getchar();
int res = 0;
while (!isdigit(c)) c = getchar();
while (isdigit(c)) res = (res << 3) + (res << 1) + c - 48, c = getchar();
return res;
}
signed main() {
freopen("map.in", "r", stdin);
freopen("map.out", "w", stdout);
n = input();
r = input();
for (register int i = 1; i <= n; i++)
for (register int j = 1; j <= n; j++)
a[i][j] = input();
for (register int i = 1; i <= n; i++)
for (register int j = 1; j <= n; j++)
s[i][j] = s[i - 1][j] + s[i][j - 1] - s[i - 1][j - 1] + a[i][j];
int x11, x22, y11, y22;
for (register int i = 1; i <= n; i++, printf("\n"))
for (register int j = 1; j <= n; j++) {
x11 = i - r > 0 ? i - r : 1;
y11 = j - r > 0 ? j - r : 1;
x22 = i + r <= n ? i + r : n;
y22 = j + r <= n ? j + r : n;
printf("%d ", s[x22][y22] - s[x11 - 1][y22] - s[x22][y11 - 1] + s[x11 - 1][y11 - 1]);
}
}
3832 在哪裏建釀酒廠
題意
一個環形,確定一個點,使得這個點到其它點的權值最小。
思路
觀察到,暴力卡卡可過。
代碼
#include <cstdio>
#include <cctype>
#include <algorithm>
long long n, ans = 1000000000000000000ll;
long long z[10001], d[10001];
inline long long input() {
char c = getchar();
long long res = 0;
while (!isdigit(c)) c = getchar();
while (isdigit(c)) res = (res << 3) + (res << 1) + c - 48, c = getchar();
return res;
}
int main() {
scanf("%lld", &n);
long long s = 0;
for (register long long i = 1; i <= n; i++)
z[i] = input(), d[i] = input(), s += d[i];
for (register long long i = 1; i <= n; i++) {
long long res = 0, dis = 0, x;
for (long long j = i + 1; j <= n + i - 1; j++) {
x = (j - 1) % n + 1;
if (i == x) continue;
dis += d[x - 1 == 0 ? n : x - 1];
res += std::min(dis, s - dis) * z[x];
}
ans = std::min(ans, res);
}
printf("%lld", ans);
}
1956 矩形
做過原題,在判斷矩形是否覆蓋時要注意,我這裏是判斷:
上下左右四種情況矩形相離,或點在矩形的四個角上。
3833 平坦的折線
題意
給出幾個點,徐要幾條平坦的折線覆蓋它們,平坦的折線定義爲任何兩個點之間連接的直線段與x軸的夾角在-45~45之間,求出最少需要的折線。
思路
把座標系轉45度,可以發現當一個點在另一個點的右上角我們就可以用同一條折線覆蓋它,按照x座標排序,我們就可以轉換成求最小不下降序列的數目,這裏就需要用到Dilworth定理(顯然我不會。
代碼
#include <cstdio>
#include <algorithm>
struct node {
int x, y;
}p[30001];
int n, ans;
int f[30001];
bool operator <(const node &a, const node &b) {
return a.x < b.x || (a.x == b.x && a.y > b.y);
}
int main() {
scanf("%d", &n);
for (int i = 1, x, y; i <= n; i++)
scanf("%d %d", &x, &y), p[i].x = x + y, p[i].y = y - x;
std::sort(p + 1, p + n + 1);
f[++ans] = p[1].y;
for (int i = 2; i <= n; i++) {
if (p[i].y > f[ans]) f[++ans] = p[i].y;
else f[std::lower_bound(f + 1, f + ans + 1, p[i].y) - f] = p[i].y;
}
printf("%d", ans);
}