HIT 2715 Matrix3(最大费用最大流)

Matrix3

My Tags   (Edit)
  Source : bin3
  Time limit : 5 sec   Memory limit : 64 M

Submitted : 302, Accepted : 74

Zhouguyue is a "驴友" and nowadays he likes traveling on an N * N matrix with a non-negative number in each grid, and each grid has a height. Zhouguyue starts his matrix travel with POINT = 0. For each travel, zhouguyue can land on any grid he wants with the help of bin3's helicopter, and then he can only move to ajacent grids whose height is less than his current height. Notice that when he is at the side of the matrix, he can also move out of the matrix. After he moves out of the matrix, he completes one travel. He adds the number in each grid he visited to POINT, and replaces it with zero. Now zhouguyue is wondering what is the maximum POINT he can obtain after he travels at most K times. Note the POINT is accumulative during the travels.

Input

The first line is a integer T indicating the number of test cases.T cases fllows. The first line of each case contains two integers N and K (1 ≤ N ≤ 50, 0 ≤ K ≤ 50) described above. The following N lines represents the matrix. You can assume the numbers in the matrix are non-negative integers and no more than 10000. The following N lines represents the height of each grid. The heghts are also non-negative integers.

Output

The maximum POINT zhouguyue can obtain after he travels at most K times.

Sample Input

1
3 2
1 2 3
3 2 1
2 4 2

3 5 3
2 1 0
1 2 3

Sample Output

17

题目:http://acm.hit.edu.cn/hoj/problem/view?id=2715

题意:就是一个矩阵,每次你可以任意选一个格子,然后可以跳到相邻的比他低的格子上去,每个格子里有分数,问连续k次能得到的分数和最大值。。。

分析:很明显的最大费用最大流。。。首先肯定要分点,把每个格子分成两个点,这两个点之间要连两条边,一条容量为1,费用为格子分数的相反数(转换为最小费用流),另一条边容量为无穷,费用为0(以下的边都是这样的边),表示格子可以多次通过,然后就是对于相邻的格子并满足条件的,也要连上一条边,注意点的分层,然后就是虚构出三个点,一个汇点,在矩阵边缘的格子都有连上她,一个源点,连到每个格子,一个总源点,连到源点,这条边要求容量为k就行了。。。

然后套模板。。。1Y

貌似hit的题很少人刷的样子,我居然是最快的- -


代码:

#include<cstdio>
#include<iostream>
using namespace std;
const int mm=66666;
const int mn=5555;
const int oo=1e9;
int src,dest,node,edge;
int dx[]={0,0,-1,1};
int dy[]={-1,1,0,0};
int ver[mm],cost[mm],flow[mm],next[mm];
int head[mn],dis[mn],p[mn],q[mn];
int h[55][55];
bool vis[mn]={0};
void prepare(int _node,int _src,int _dest)
{
    node=_node,src=_src,dest=_dest;
    for(int i=0;i<node;++i)head[i]=-1;
    edge=0;
}
void addedge(int u,int v,int f,int c)
{
    ver[edge]=v,flow[edge]=f,cost[edge]=c,next[edge]=head[u],head[u]=edge++;
    ver[edge]=u,flow[edge]=0,cost[edge]=-c,next[edge]=head[v],head[v]=edge++;
}
bool Spfa()
{
    int i,u,v,l,r=0,tmp;
    for(i=0;i<node;++i)dis[i]=oo;
    dis[q[r++]=src]=0;
    p[src]=p[dest]=-1;
    for(l=0;l!=r;(++l==mn)?l=0:l)
        for(i=head[u=q[l]],vis[u]=0;i>=0;i=next[i])
            if(flow[i]&&dis[v=ver[i]]>(tmp=dis[u]+cost[i]))
            {
                dis[v]=tmp;
                p[v]=i^1;
                if(vis[v])continue;
                vis[q[r++]=v]=1;
                if(r==mn)r=0;
            }
    return p[dest]>-1;
}
int Spfaflow()
{
    int i,delta,ret=0;
    while(Spfa())
    {
        for(i=p[dest],delta=oo;i>=0;i=p[ver[i]])
            if(flow[i^1]<delta)delta=flow[i^1];
        for(i=p[dest];i>=0;i=p[ver[i]])
            flow[i]+=delta,flow[i^1]-=delta;
        ret-=delta*dis[dest];
    }
    return ret;
}
int main()
{
    int i,j,x,y,k,n,m,t;
    scanf("%d",&t);
    while(t--)
    {
        scanf("%d%d",&n,&m);
        prepare(n*n*2+3,n*n*2+1,n*n*2+2);
        for(i=0;i<n;++i)
            for(j=1;j<=n;++j)
            {
                scanf("%d",&k);
                addedge(0,i*n+j,oo,0);
                addedge(i*n+j,n*n+i*n+j,1,-k);
                addedge(i*n+j,n*n+i*n+j,oo,0);
            }
        for(i=1;i<=n;++i)
            for(j=1;j<=n;++j)
                scanf("%d",&h[i][j]);
        for(i=1;i<=n;++i)
            for(j=1;j<=n;++j)
                for(k=0;k<4;++k)
                {
                    x=i+dx[k];
                    y=j+dy[k];
                    if(x<1||x>n||y<1||y>n||h[x][y]>=h[i][j])continue;
                    addedge(n*n+i*n-n+j,x*n-n+y,oo,0);
                }
        for(i=1;i<=n;++i)
            for(j=1;j<=n;++j)
                if(i==1||j==1||i==n||j==n)
                    addedge(n*n+n*i-n+j,dest,oo,0);
        addedge(src,0,m,0);
        printf("%d\n",Spfaflow());
    }
    return 0;
}



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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值