給定乙個n×n的棋盤,棋盤上每個位置要麼為空要麼為障礙。定義棋盤上兩個位置(x,y),(u,v)能互相攻擊當前僅
當滿足以下兩個條件:
1:x=u或y=v
2:對於(x,y)與(u,v)之間的所有位置,均不是障礙。
現在有q個詢問,每個詢問給定ki,要求從棋盤中選出ki個空位置來放棋子,問最少互相能攻擊到的棋子對數是多少?
第一行乙個整數n。
接下來輸入乙個n×n的字元矩陣,乙個位置若為.,則表示這是乙個空位置,若為#,則為障礙。
第n+2行輸入乙個整數q代表詢問個數。
接下來q行,每行乙個整數k,代表要放的棋子個數。
n ≤ 50, q ≤ 10000, k ≤ 棋盤中空位置數量
輸出共q行,每行代表對應詢問的最少的互相能攻擊到的棋子對數。
4..#.
####
..#.
..#.
1 72
題解:還是集訓原題~
如果你做過了bzoj4554遊戲那道題,還做過了修車,那麼這道題豈不是很水?
如果沒有障礙,那麼我們顯然是將網格按照行和列拆分,然後每行向每列連邊,然後搞一搞,不過有障礙怎麼辦呢?
我們如果一行中有a段連續的障礙,我們認為每段障礙都將這行切成了兩段,那麼一共被切成了a+1段。類似地,每列也都被切成了好幾段。那麼我們得到了一堆行和一堆列,現在我們想在它們之間連邊。
先考慮每一段行,在這個行中放乙個棋子,產生的衝突數為0,再放1枚,衝突數+1,再放1枚,衝突數+2。。。那麼我們顯然可以考慮拆邊。就有了建圖方法:
設第i個行(被切過的)為hi,第j個列為rj,那麼:
1.s -> hi 連若干條邊,其中第k條費用為k-1,容量為1。
2.對於網格中的非障礙點(i,j),hi -> rj 費用為0,容量為1。
3.rj -> t 連若干條邊,其中第k條費用為k-1,容量為1。
由於考試的時候我比較慫,所以寫的動態加邊,好像沒什麼必要~
練完邊,跑完費用流後,再一起處理詢問就好啦~
#include #include #include #include #define p(a,b) ((a-1)*n+b)using namespace std;
int n,m,s,t,cnt,sum,tot,mf,nx,ny;
char str[60][60];
int to[1000000],next[1000000],cost[1000000],flow[1000000],dis[10000],inq[10000],pe[10000],pv[10000],head[10000];
int ans[10000],bx[60][60],by[60][60],lx[10000],ly[10000],ux[10000],uy[10000];
queueq;
void add(int a,int b,int c,int d)
int bfs()
} }return dis[t]<0x3f3f3f3f;
}int main()
} for(j=1;j<=n;j++) }
s=0,t=nx+ny+1;
for(i=1;i<=nx;i++) add(s,i,0,1);
for(i=1;i<=ny;i++) add(i+nx,t,0,1);
while(bfs())
tot+=mf*dis[t];
ans[sum+=mf]=tot;
for(i=t;i!=s;i=pv[i]) flow[pe[i]]-=mf,flow[pe[i]^1]+=mf;
} scanf("%d",&m);
for(i=1;i<=m;i++)
return 0;
}
bzoj4930 棋盤 費用流
題目描述 給定乙個n n的棋盤,棋盤上每個位置要麼為空要麼為障礙。定義棋盤上兩個位置 x,y u,v 能互相攻擊當前僅 當滿足以下兩個條件 1 x u或y v 2 對於 x,y 與 u,v 之間的所有位置,均不是障礙。現在有q個詢問,每個詢問給定ki,要求從棋盤中選出ki個空位置來放棋子,問最少互相...
hdu3667 最小費用流 拆邊題
第一道拆邊題 用bellman ford以967ms險過.先說一下大體的題意 輸入n m k 分別指城市的個數 m條邊 現在需要把k個單位的物品從城市1運往城市n 接下來的m行 每一行輸入四個數 u i,v i,a i,ci 代表從城市u到城市v有一條單向路 容量為c 如果在這條路上運送x個單位的物...
bzoj 1927 星際競速(拆點費用流)
題目鏈結 好嘛,現在我要正式用某神犇的部落格上的題的順序開始刷題了。這道題將每個能力爆發模式的費用,即單點費用拆成兩個點,再加邊。要加入乙個源點和匯點。本蒟蒻只會寫有點耗時的spfa版,若有那個神犇會zkw費用流,請教一下 include include include includeusing n...