【Codeforces944F】Game with Tokens

本文探讨了一种黑白棋游戏的策略问题,其中白棋和黑棋轮流移动,目标是使黑棋能够在有限步数内包围并阻止白棋移动。文章通过分析棋盘布局和移动规则,提出了一种有效的方法来确定初始状态下白棋可能失败的位置。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

time limit per test:2 seconds
memory limit per test:256 megabytes
input:standard input
output:standard output

Description
Consider the following game for two players. There is one white token and some number of black tokens. Each token is placed on a plane in a point with integer coordinates x and y.

The players take turn making moves, white starts. On each turn, a player moves all tokens of their color by 1 to up, down, left or right. Black player can choose directions for each token independently.

After a turn of the white player the white token can not be in a point where a black token is located. There are no other constraints on locations of the tokens: positions of black tokens can coincide, after a turn of the black player and initially the white token can be in the same point with some black point. If at some moment the white player can’t make a move, he loses. If the white player makes 10100500 moves, he wins.

You are to solve the following problem. You are given initial positions of all black tokens. It is guaranteed that initially all these positions are distinct. In how many places can the white token be located initially so that if both players play optimally, the black player wins?

Input
The first line contains a single integer n (1 ≤ n ≤ 105) — the number of black points.

The (i + 1)-th line contains two integers xi, yi ( - 105 ≤ xi, yi,  ≤ 105) — the coordinates of the point where the i-th black token is initially located.

It is guaranteed that initial positions of black tokens are distinct.

Output
Print the number of points where the white token can be located initially, such that if both players play optimally, the black player wins.

Examples
input1

4
-2 -1
0 1
0 -3
2 -1

output1

4

input2

4
-2 0
-1 1
0 -2
1 -1

output2

2

input3

16
2 1
1 2
-1 1
0 1
0 0
1 1
2 -1
2 0
1 0
-1 -1
1 -1
2 2
0 -1
-1 0
0 2
-1 2

output3

4

Note
In the first and second examples initial positions of black tokens are shown with black points, possible positions of the white token (such that the black player wins) are shown with white points.

The first example:

..1..
..0..
10.01
..0..
..1..

let 1 take the place of black tokens and the white token can be lain at the 0 block
The second example:

.1..
10..
..01
..1.

In the third example the white tokens should be located in the inner square 2 × 2, to make the black player win.

......
.1111.
.1111.
.1111.
.1111.
......

题目大意

假设棋盘上有若干黑棋和一个白棋,每一轮白起先走到一个没放黑棋的四联通的位置,若四周都有黑棋则输,接下来黑棋每一子都要往前后左右一个方向走,可以与其它子重合,在最优策略下黑棋想要困住白棋
现在给出若干个黑棋的位置,问有多少个位置放白棋会输


Analysis
对于一颗黑棋和一颗白棋,若黑棋的横纵坐标之和与白棋的奇偶性相同,那么黑棋永远无法挡住白棋
若白棋朝黑棋走,黑棋也朝白棋走,否则按白棋的方向走

..1→    .←1.
....    .↑..
.0→.    .0..

这样,当且仅当白棋的以下四个方向上都有点才能被抓住
anal

这样将棋盘旋转45度,就变成了扫描线的问题了

#include<cstring>
#include<cstdio>
#include<algorithm>
#define N 100100
#define bord 200000
#define fo(i,a,b) for(int i=a,E=b;i<=E;i++)
#define fd(i,a,b) for(int i=a,E=b;i>=E;i--)

using namespace std;

int n,mx[N*4],mn[N*4];
long long ans;
struct token{int x,y;}d[N];
bool cmp(token a,token b){return a.x<b.x;}

int main(){
    scanf("%d",&n);
    fo(i,1,n){
        int x,y;scanf("%d %d",&x,&y);
        d[i]=(token){x+y,x-y};
    }sort(d+1,d+n+1,cmp);
    int l[2],r[2],a=1;
    l[0]=l[1]=bord*2+2,r[0]=r[1]=-bord*2-2;
    fo(i,0,bord*2)mx[i]=l[0],mn[i]=r[0];
    fo(i,-bord,bord){
        int w=(i%2+2)&1;
        mn[i+bord]=max(mn[i+bord],l[1^w]);
        mx[i+bord]=min(mx[i+bord],r[1^w]);
        for(;a<=n && d[a].x==i;++a){
            l[w]=min(l[w],d[a].y);r[w]=max(r[w],d[a].y);
        }
    }
    l[0]=l[1]=bord*2+2,r[0]=r[1]=-bord*2-2;a=n;
    fd(i,bord,-bord){
        int w=(i%2+2)&1;
        mn[i+bord]=max(mn[i+bord],l[1^w]);
        mx[i+bord]=min(mx[i+bord],r[1^w]);
        for(;a && d[a].x==i;--a){
            l[w]=min(l[w],d[a].y);r[w]=max(r[w],d[a].y);
        }
    }
    fo(i,-bord,bord){
        int w=(i%2+2)&1;
        if((mn[i+bord]%2+2)%2!=w)++mn[i+bord];
        if((mx[i+bord]%2+2)%2!=w)--mx[i+bord];
        if(mx[i+bord]>=mn[i+bord])ans+=(mx[i+bord]-mn[i+bord])/2+1;
    }printf("%I64d",ans);
    return 0;
}
Codeforces 2123F 问题中,目标是通过重新排列数组 $ a $ 来最小化不动点的数量。所谓“不动点”是指在重新排列后的数组中满足 $ a_i = i $ 的位置。该问题要求设计一种策略,以最优方式重新排列数组元素,使得这样的不动点数量最少。 为了解决这个问题,可以采用贪心算法和图论思想相结合的策略: - 首先,观察到如果某个值 $ i $ 出现了多次(即 $ a_i = i $),那么这些重复的值必须被移动到其他位置,以消除不动点。 - 对于那些没有出现在其索引上的值(例如 $ a_i \neq i $),可以通过交换操作将其移动到合适的位置,从而避免产生新的不动点。 一个有效的解决方案可以基于以下步骤: 1. 构建一个映射表,记录每个值出现的位置。 2. 找出所有当前值等于其索引的位置(即当前的不动点)。 3. 尝试通过交换来消除这些不动点。优先考虑将这些值移动到未被占用的位置,并确保不会引入新的不动点。 4. 在无法完全消除所有不动点的情况下,选择最优的交换策略以尽可能减少不动点的数量。 以下是 Python 中的一个示例实现,用于解决此类问题的基本思路: ```python def minimize_fixed_points(n, a): pos = {} fixed_points = [] # 记录每个值的出现位置,并找出初始的不动点 for i in range(n): if a[i] == i + 1: fixed_points.append(i) if a[i] not in pos: pos[a[i]] = [] pos[a[i]].append(i) # 如果没有重复的值,则可以直接交换以消除所有不动点 result = a[:] for i in fixed_points: found = False for val in pos: if val != i + 1 and len(pos[val]) > 0: j = pos[val].pop() result[i], result[j] = result[j], result[i] found = True break if not found: # 特殊情况处理:当只剩下一个值时 for j in range(n): if j != i and result[j] != j + 1: result[i], result[j] = result[j], result[i] break return result # 示例输入 n = int(input()) a = list(map(int, input().split())) result = minimize_fixed_points(n, a) print(' '.join(map(str, result))) ``` 此代码实现了上述逻辑,并尝试通过交换来最小化不动点的数量。对于大多数情况,它能够有效消除所有不动点;在某些特殊情况下(例如所有值都唯一且存在多个不动点),则需要特别处理。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值