給定乙個 n×
n 的棋盤,棋盤上每個位置要麼為空要麼為障礙。定義棋盤上兩個位置 (x
,y),
(u,v
) 能互相攻擊當前僅當滿足以下兩個條件: 1.x
=u或 y=
v 2.對於 (x
,y) 與 (u
,v) 之間的所有位置,均不是障礙。
現在有
q 個詢問,每個詢問給定 ki
,要求從棋盤中選出 ki
個空位置來放棋子,問最少互相能攻擊到的棋子對數是多少? n≤
50 , q≤
10000
, k≤
棋盤中空
位置數量
本來是道費用流大裸題,結果只有我沒想出來。考慮棋盤模型,一排表示行,一排表示列,然後棋子相互攻擊的貢獻是遞增的,所以
s 到表示行的點和 表示列的點到
t之間連遞增費用的邊,如果乙個位置不是障礙,就把對應行列連起來,障礙隔開的行和列只要建不同的點即可。
#include
const int n = 55;
const int p = n * n * 2;
const int inf = 1e9;
template void read(t &x)
int n, a[n][n], b[n][n], first[p], s, q[p + 10], dis[p], from[p], ans[n * n], cnt, line, s, t, q, x;
bool inq[p];
char ch[n][n];
struct edgemp[n*n
*n*n
*2];
void ins(int
x, int
y, int f, int v) ; first[x] = s;
mp[++s] = (edge) ; first[y] = s;
}bool spfa()
} }inq[q[head++]] = 0;
if (head > p) head = 1;
}return dis[t] < inf;
}void mcf(int i)
int main()
line = cnt;
for (int j=1; j <= n; j++)
for (int i=1; i <= n; i++)
s = 0; t = cnt + 1; s = 1;
for (int j=1; j <= n; j++)
for (int i=1; i <= n; i++)
if (ch[i][j] == '.')
ins(a[i][j], b[i][j], 1, 0);
for (int i=1; i <= line; i++)
for (int j=0; j < n; j++)
ins(s, i, 1, j);
for (int i=line + 1; i <= cnt; i++)
for (int j=0; j < n; j++)
ins(i, t, 1, j);
for (int i=1; spfa(); i++) mcf(i);
for (read(q); q--;)
read(x),
printf("%d\n", ans[x]);
return
0;}
程式設計訓練 棋盤
棋盤是指乙個行和列編號從1 n的nxn的二進位制矩陣,當行號和列號之和為偶數時該矩陣對應位置為黑色的 1 否則為白色的 0 以下圖示為n 1 2 3時的棋盤。給出乙個nxn的二進位制矩陣,請找出位於該矩陣內的最大尺寸的完整棋盤,以及最大尺寸棋盤的數量 棋盤可以交疊 每個測試用例的第一行是乙個正整數n...
日常訓練 壓縮
巨大的文字往往令人頭疼,特別是文字內容有大量重複的情況下,巨大的文字不便於運輸和閱讀,於是我們提出了noip nonsense obivous index pattern 荒謬的顯然索引法 一種 有效的 壓縮文字的方法。noip壓縮後的格式很特別,乙個文字壓縮後由若干個單元組成,每個單元由3部分組成...
日常訓練 Tree
j 對於h u j 時間複雜度的證明也是比較經典了,每次列舉的是sz eu s zev 相當於每次從a,b 中各任選一點,它們的lc a 為 u 這樣的點對列舉不會重複,因此總的時間複雜度為o n2 include include include include include using name...