UVa 1515 Pool construction

You are working for the International Company for Pool Construction, a construction company which
specializes in building swimming pools. A new client wants to build several new pool areas.
A pool area is a rectangular grid of w × h square patches, consisting of zero or more (possibly
disconnected) pools. A pool consists of one or multiple connected hole patches, which will later be
filled with water. In the beginning, you start with a piece of land where each patch is either a hole in
the ground (’.’) or flat grass (’#’). In order to transform this land into a pool area, you must adhere
to the following:
• You can leave a patch as it is. This costs nothing.
• If the patch is grass in the beginning, you can dig a hole there. This costs d EUR.
• If the patch is a hole in the beginning, you can fill the hole and put grass on top. This costs f
EUR.
• You must place special boundary elements along each edge running between a final grass patch
and a final hole patch, to ensure that water does not leak from the pool. This costs b EUR per
boundary element.
• The outermost rows and columns of the pool area must always be grass.
You are given the task of calculating the cost of the cheapest possible pool area given the layout of
the existing piece of land.
Input
On the first line a positive integer: the number of test cases, at most 100. After that per test case:
• one line with two integers w and h (2 ≤ w, h ≤ 50): the width and height of the building site.
• one line with three integers d, f and b (1 ≤ d, f, b ≤ 10000): the costs for digging a new hole,
filling an existing hole, and building a boundary element between a pool and grass patch.
• h lines of w characters each, denoting the layout of the original building site.
Output
Per test case:
• one line with an integer: the cost of building the cheapest possible pool area from the original
piece of land.
Sample Input
3
3 3
5 5 1
#.#
#.#
###
5 4
1 8 1
#..##
##.##
#.#.#
#####
2 2
27 11 11
#.
.#
Sample Output
9
27

22

~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

最小割~

一共交了三十几次,不是T就是WA,开始怀疑人生的时候发现是数组开小了……

对于边上的洞,先统一填成草,然后建立源点0,汇点n*m+1,从0向所有'#'连边,但是因为边上不能有洞,所以向边上的'#'连边的边权是inf,其余是d,表示用d可以把它改成洞;从所有'.'向汇点连边,边权为f,意义同上;最后把每个格子都和上下左右连成无向边,边权为b,表示围起来,然后求最小割即可~


#include<cstdio>
#include<cstring>
#include<iostream>
#include<queue>
using namespace std;
#define inf 1<<29

int t,n,m,d,f,b,fi[3001],ne[100100],w[100100],v[100100],cnt,ans,now,tot,dis[3001];
char s[101][101];
queue<int> q;

void add(int u,int vv,int val)
{
	w[++cnt]=vv;v[cnt]=val;ne[cnt]=fi[u];fi[u]=cnt;
	w[++cnt]=u;v[cnt]=0;ne[cnt]=fi[vv];fi[vv]=cnt;
}

bool bfs()
{
	memset(dis,0,sizeof(dis));
	q.push(0);dis[0]=1;
	while(!q.empty())
	{
		int k=q.front();q.pop();
		for(int i=fi[k];i;i=ne[i])
		  if(v[i] && !dis[w[i]])
		  {
		  	dis[w[i]]=dis[k]+1;q.push(w[i]);
		  }
	}
	return dis[tot];
}

int findd(int u,int vv)
{
	if(u==tot || !vv) return vv;
	for(int i=fi[u],kkz;i;i=ne[i])
	  if(dis[w[i]]==dis[u]+1 && (kkz=findd(w[i],min(v[i],vv))))
	  {
	  	v[i]-=kkz;v[i^1]+=kkz;return kkz;
	  }
	return dis[u]=0;
}

int main()
{
	scanf("%d",&t);
	while(t--)
	{
		scanf("%d%d%d%d%d",&m,&n,&d,&f,&b);tot=n*m+1;cnt=1;ans=0;
		for(int i=1;i<=n;i++) scanf("%s",s[i]+1);
		for(int i=0;i<=tot;i++) fi[i]=0;
		for(int i=1;i<=n;i++)
		  for(int j=1;j<=m;j++)
		  {
		  	if(i==1 || i==n || j==1 || j==m)
			{
			  	add(0,(i-1)*m+j,inf);
			  	if(s[i][j]=='.') ans+=f;
			}
		  	else if(s[i][j]=='#') add(0,(i-1)*m+j,d);
			else add((i-1)*m+j,tot,f); 
			if(i>1) add((i-1)*m+j,(i-2)*m+j,b),add((i-2)*m+j,(i-1)*m+j,b);
			if(j>1) add((i-1)*m+j-1,(i-1)*m+j,b),add((i-1)*m+j,(i-1)*m+j-1,b);
		  }
		while(bfs()) while(now=findd(0,inf)) ans+=now;
		printf("%d\n",ans);
	}
	return 0;
}


  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值