CQOI2006 NKOJ2004 移動棋子

2021-07-22 03:41:26 字數 2017 閱讀 9315

【cqoi2006】移動棋子

time limit:50000ms  memory limit:65536k

case time limit:5000ms

description

在乙個n*n的棋盤上有n枚棋子。每次可以把一枚棋子往上、下、左、右方向之一移動一格,最後排成一行、一列或者主、副對角線上(因此一共有2n+2條可能的目標狀態),要求移動次數最小。 

棋盤上有一些位置是障礙,棋子在任何時候都不能經過。棋子的初始位置保證不在障礙物上。任兩枚棋子不能在同時到達 同乙個格仔。 

input

第一行包含兩個整數n, m,表示棋子的個數(它也是棋盤的邊長)和障礙的個數。以下n行,每行兩個整數(x, y),表示第i個棋子的座標(1<=x, y<=n),以下m行,每行給出乙個障礙物的座標。假設這n+m個座標兩兩不重合。

output

乙個整數,表示最小移動步數。如果無解,輸出-1。

sample input

5 1

1 22 4

3 45 1

5 31 1

sample output

6
hint

50%的資料滿足:2<=n<=15,m=0 

100%的資料滿足:2<=n<=50, 0<=m<=100

分析:不需要考慮每個棋子的移動情況,只管最終狀態(2n+2種),於是最小費用最大流。

建圖:

s向每個棋子連邊,flow = 1,cost = 0

每個棋子向每個最終位置連邊,flow = inf,cost = bfs

每個最終位置向t連邊,flow = 1,cost = 0

預處理出每個棋子到棋盤上的每個位置所需的最小步數,這裡採用的是bfs

#include#include#include#include#include#includeusing namespace std;

const int inf=1000000000;

int dx[4]=;

int dy[4]=;

int n,m;

int n;

int maxflow;

int mincost;

int tot_edge=0;

int flow,cost;

int dis[10005],path[10005];

int a[10005];

bool flag[10005];

bool obstacle[1005][1005];

int map[55][55][55];

bool vis[55][55];

struct line;

line edge[100005];

int last[10005],_next[100005];

void clean()

void add_edge(int x,int y,int l,int acc)

bool findpath()

dis[n+1]=path[n+1]=0;

flag[n+1]=true;

q.push(n+1);

while(q.size())

}} }

if(dis[n+2]>n>>m;

n=2*n;

for(i=1;i<=n;i++)

for(i=1;i<=m;i++)

for(i=1;i<=n;i++)

}} for(j=1;j<=n;j++)

} map[i][point[i].x][point[i].y]=0;

/*cout<

cout<

CQOI2006 簡單題 線段樹

水。區間修改,單點查詢。用線段樹維護區間 l,r 內的所有 1 的個數,懶標記表示為當前區間是否需要反轉 相對於區間當前狀態 下方標記時懶標記取反即可。include include define sl x 1 define sr x 1 1 define maxn 100010 using nam...

2618 Cqoi2006 凸多邊形

逆時針給出 n個凸多邊形的頂點座標,求它們交的面積。例如n 2時,兩個凸多邊形如下圖 則相交部分的面積為5.233。第一行有乙個整數n,表示凸多邊形的個數,以下依次描述各個多邊形。第i個多邊形的第一行包含乙個整數mi 表示多邊形的邊數,以下mi 行每行兩個整數,逆時針給出各個頂點的座標。輸出檔案僅包...

CQOI 2006 線段樹之簡單題

description 有乙個n個元素的陣列,每個元素初始均為0。有m條指令,要麼讓其中一段連續序列數字反轉 0變1,1變0 操作1 要麼詢問某個元素的值 操作2 例如當n 20時,10條指令如下 第一行包含兩個整數n,m,表示陣列的長度和指令的條數,以下m行,每行的第乙個數t表示操作的種類。若t ...