【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 1sample output1 22 4
3 45 1
5 31 1
6hint
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 ...