Retiling-Google Codejam 2021 Round 2
作者:互联网
Retiling-Google Codejam 2021 Round 2第四题
Cody-Jamal’s latest artistic installment is a tiled kitchen floor that can be retiled to different patterns. The floor consists of a matrix of R rows and C columns of square tiles. Each tile is reversible, one side is magenta and the other one is green.
To retile the kitchen, there are two allowed operations:
flip a tile, changing its visible color from magenta to green, or vice versa, and swap two adjacent tiles (horizontally or vertically, but not diagonally), without flipping either.
Viewing Cody-Jamal’s artistic floor is free, but interacting with it is not. Performing a single flip operation costs F coins, and performing a single swap operation costs S coins.
You can see the current state of the floor and want to turn it into a particular pattern. What is the minimum amount of coins you need to spend to achieve your goal?
题目大意:
你需要在一个长宽分别为 R , C ( 1 ≤ R , C ≤ 10 ) R,C(1\leq R,C\leq10) R,C(1≤R,C≤10)的房间重新铺地砖。地砖正面是绿色,背面是红色,你每次可以把一个地砖翻面,或是把两个相邻的地砖(仅限上下左右相邻)交换。一次翻面花费为 F F F,一次交换花费为 S S S。现在给定所有地砖位置的初始颜色和最终颜色,试计算最小花费。
思路分析:
注意到对于每一块地砖,在最优解法中不会既被翻面又被交换:假设地砖 x x x和地砖 y y y交换后又被翻面,这等价于我们翻面地砖 y y y,这样花费显然更小。同时,交换操作显然只在颜色不同的两个地砖之间进行。
那么解法就很显然了:我们考虑所有初始颜色和最终颜色不一样的位置,根据颜色分组,这就是一个二分图的匹配问题:我们考虑匹配两个起始颜色不同的地砖进行匹配,完成最优匹配后剩下的地砖进行翻转操作即可。交换的花费为 m i n ( d i s t ( x , y ) × S , 2 × F ) min(dist(x,y)\times S,2\times F) min(dist(x,y)×S,2×F)(我们也可以选择直接把两块地砖都翻面)。我们可以使用最优匹配算法解决这个问题。由于点数是100,边数最多是50 × \times × 50=2500条,我们过时限是绰绰有余的。
这里我直接采用了费用流算法,时间上不会有什么差异,主要是KM写得少。
重要部分代码:
加边:
for(int i=0;i<r*c;i++){
if(diff[i])countdi++;//算一下总共需要改的地砖
if(color[i]=='G'&&diff[i])//绿色且需要修改的地砖
{
for(int j=i+1;j<r*c;j++){
if(color[j]=='M'&&diff[j])//与红色且需要修改的地砖配对
{
add(i,j,1,min(dist(i,j)*costS,2*cost*F))//流量为1,费用如上所述;
}
}
add(S,i,1,0)//别忘了连条边到源点;
}
else if(if(color[i]=='M'&&diff[i]))add(i,T,1,0);//红色的需要改的要连一条边到汇点
}
费用流板子:
int cost=0,flow=0;
while(spfa()){
flow+=limit[T];
cost+=limit[T]*dis[T];
for(int i=T;i!=S;i=to[pre[i]^1]){
f[pre[i]]-=limit[T];
f[pre[i]^1]+=limit[T];
}
}
cost+=costF*(countdi-flow*2);//把未匹配成功的地砖翻面费用加上·1
费用流spfa板子:
inline bool spfa(){
memset(dis,0x3f,sizeof dis);
memset(limit,0,sizeof limit);
dis[S]=0,q.push(S),limit[S]=0x3f3f3f3f,st[S]=true;
while(!q.empty()){
int x=q.front();
q.pop();
st[x]=false;
for(int i=h[x];~i;i=nex[i]){
int j=to[i];
if(f[i]&&dis[j]>dis[x]+w[i]){
dis[j]=dis[x]+w[i];
limit[j]=min(limit[x],f[i]);
pre[j]=i;
if(!st[j]){
q.push(j);
st[j]=true;
}
}
}
}
return limit[T]>0;
}
第二轮压轴题,二分图模型比较明显,所以说并不难。
标签:Google,地砖,int,st,翻面,Retiling,limit,2021,dis 来源: https://blog.csdn.net/Layomiiety/article/details/116886768