codevs 1227 方格取数 2

 时间限制: 1 s
 空间限制: 128000 KB
 题目等级 : 大师 Master
题目描述 Description

给出一个n*n的矩阵,每一格有一个非负整数Aij,(Aij <= 1000)现在从(1,1)出发,可以往右或者往下走,最后到达(n,n),每达到一格,把该格子的数取出来,该格子的数就变成0,这样一共走K次,现在要求K次所达到的方格的数的和最大

输入描述 Input Description

第一行两个数n,k(1<=n<=50, 0<=k<=10)

接下来n行,每行n个数,分别表示矩阵的每个格子的数

输出描述 Output Description

一个数,为最大和

样例输入 Sample Input

3 1

1 2 3

0 2 1

1 4 2

样例输出 Sample Output

11

数据范围及提示 Data Size & Hint

1<=n<=50, 0<=k<=10

 

拆点+费用流

把每个点拆成两个 x,y 

x,y之间建两条边

第一条 流量为1 费用为点值

第二条 流量inf 费用0  

目的是表示 可以经过无数次,但价值只能取一次 

屠龙宝刀点击就送

#include <ctype.h>
#include <cstdio>
#include <queue>
#define N 100000
#define inf 0x7ffffff
using namespace std;
void read(int &x)
{
    x=0;bool f=0;
    register char ch=getchar();
    for(;!isdigit(ch);ch=getchar()) if(ch=='-') f=1;
    for(;isdigit(ch);ch=getchar()) x=x*10+ch-'0';
}
struct Edge
{
    int next,to,value,flow;
    Edge (int next=0,int to=0,int flow=0,int value=0) : next(next),to(to),flow(flow),value(value) {} 
}edge[N<<1];
bool vis[N];
int flow[N],dis[N],head[N],cnt=1,fa[N],n,k,tot;
void insert(int u,int v,int w,int l)
{
    edge[++cnt]=Edge(head[u],v,w,l);
    head[u]=cnt;
}
int min(int a,int b) {return a>b?b:a;} 
bool spfa(int s,int t)
{
    for(int i=s;i<=t;i++) {flow[i]=inf;dis[i]=0xefefefef;vis[i]=0;}
    vis[s]=1;
    dis[s]=0;
    fa[s]=0;
    queue<int>Q;
    Q.push(s);
    while(!Q.empty())
    {
        int now=Q.front();
        Q.pop();
        vis[now]=0;
        for(int i=head[now];i;i=edge[i].next)
        {
            int v=edge[i].to;
            if(dis[v]<edge[i].value+dis[now]&&edge[i].flow>0)
            {
                dis[v]=dis[now]+edge[i].value;
                flow[v]=min(flow[now],edge[i].flow); 
                fa[v]=i;
                if(!vis[v])
                {
                    vis[v]=1;
                    Q.push(v); 
                }
            }
        }
    }
    return dis[t]>0;
}
int dinic(int s,int t)
{
    int sum=0;
    for(;spfa(s,t);)
    {
        int x=flow[t];
        for(int i=t;i!=s&&i;i=edge[fa[i]^1].to)
        {
            edge[fa[i]].flow-=x;
            edge[fa[i]^1].flow+=x;
        }
        sum+=x*dis[t];
    }
    return sum;
}
int main()
{
    read(n);
    read(k);
    for(int i=1;i<=n;i++)
    {
        for(int a,j=1;j<=n;j++)
        {
            read(a);
            tot++;
            insert(tot*2,tot*2+1,1,a);
            insert(tot*2+1,tot*2,0,-a);
            insert(tot*2,tot*2+1,inf,0);
            insert(tot*2+1,tot*2,0,0);
            if(j!=n)
            {
                insert(tot*2+1,(tot+1)*2,inf,0);
                insert((tot+1)*2,tot*2+1,0,0);
            }
            if(i!=n)
            {
                insert(tot*2+1,(tot+n)*2,inf,0);
                insert((tot+n)*2,tot*2+1,0,0);
            }
        }
    }
    insert(1,2,k,0);
    insert(2,1,0,0);
    insert(tot*2+1,tot*2+2,k,0);
    insert(tot*2+2,tot*2+1,0,0);
    printf("%d",dinic(1,tot*2+2));
    return 0;
}

 

posted @ 2017-07-23 08:55  杀猪状元  阅读(177)  评论(0编辑  收藏  举报