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;
}
时间: 2024-11-14 02:50:33

codevs 1227 方格取数 2的相关文章

1227 方格取数 2

题目描述 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 Descriptio

codevs——T1043 方格取数

http://codevs.cn/problem/1043/  时间限制: 1 s 空间限制: 128000 KB 题目等级 : 钻石 Diamond 题解 查看运行结果 题目描述 Description 设有N*N的方格图(N<=10,我们将其中的某些方格中填入正整数,而其他的方格中则放入数字0.如下图所示(见样例): 某人从图的左上角的A 点出发,可以向下行走,也可以向右走,直到到达右下角的B点.在走过的路上,他可以取走方格中的数(取走后的方格中将变为数字0). 此人从A点到B 点共走两次,

CodeVs 1043 方格取数

$n \times n$ 的方格,每个格子有个自然数.一人在方格中,只能向右或下走.从左上角到右下角走两次,问最大可以取得多大的数字(每个数字取了就没了,也就是说两次经过同一个位置只能得到一个值). 考虑两次一起走,每一行经过的段是两个线段假设是 [a, b] 和 [c, d].当前一行状态是 [a, b] [c, d] 时转移是来自上一行的 b 等于这一行的 a, 并且上一行的 d 等于这一行的 c. 这样的话复杂度是 $O(n^9)$,大概是不能过的,但是考虑一下剪枝,可以让 $c \ge

tyvj 1884 [NOIP2000T4]方格取数 || codevs 1043 dp

P1884 [NOIP2000T4]方格取数 时间: 1000ms / 空间: 131072KiB / Java类名: Main 背景 [noip2000T4]方格取数 描述 设有N*N的方格图(N<=10,我们将其中的某些方格中填入正整数,而其他的方格中则放入数字0.如下图所示(见样例):某人从图的左上角的A 点出发,可以向下行走,也可以向右走,直到到达右下角的B点.在走过的路上,他可以取走方格中的数(取走后的方格中将变为数字0).此人从A点到B 点共走两次,试找出2条这样的路径,使得取得的数

[CODEVS 1043] Noip 2000 方格取数

1043 方格取数 时间限制: 1s  空间限制: 128000 KB 题目描述 Description 设有N*N的方格图(N<=10,我们将其中的某些方格中填入正整数,而其他的方格中则放入数字0.如下图所示(见样例): 某人从图的左上角的A 点出发,可以向下行走,也可以向右走,直到到达右下角的B点.在走过的路上,他可以取走方格中的数(取走后的方格中将变为数字0). 此人从A点到B 点共走两次,试找出2条这样的路径,使得取得的数之和为最大. 输入描述 Input Description 输入的

【codevs1907】方格取数3(最大流最小割定理)

网址:http://codevs.cn/problem/1907/ 题意:在一个矩阵里选不相邻的若干个数,使这些数的和最大. 我们可以把它看成一个最小割,答案就是矩阵中的所有数-最小割.先把矩阵按国际象棋棋盘黑白染色(即把相邻的点分别染成白色和黑色),然后黑点连源点,白点连汇点.割掉一个点到源/汇的边就是不选择这个点,最后的目的就是使源到汇不连通(不引发题目不能选择位置相邻的数的矛盾). 然而最小割怎么求呢? 于是我们就要引入一个定理:最大流最小割定理.它的意思就是说,在一个图中,a点到b点的最

线性规划与网络流24题●09方格取数问题&amp;13星际转移问题

●(做codevs1908时,发现测试数据也涵盖了1907,想要一并做了,但因为"技术"不佳,搞了一上午) ●09方格取数问题(codevs1907  方格取数3) 想了半天,也没成功建好图: 无奈下参考题解,说是本题要求二分图点权最大独立集,然后可以由结论:"最大点权独立集 = 所有点权 - 最小点权覆盖集 = 所有点权 - 最小割集 = 所有点权 - 网络最大流"转化到求最大流(我真的很懵逼,但又感觉很有道理): 下面附上solution:(自己领悟吧) (不懂

hdu 1565 方格取数(2)(网络流之最大点权独立集)

题目链接:hdu 1565 方格取数(2) 题意: 有一个n*m的方格,每个方格有一个数,现在让你选一些数.使得和最大. 选的数不能有相邻的. 题解: 我们知道对于普通二分图来说,最大独立点集 + 最小点覆盖集 = 总点数,类似的,对于有权的二分图来说,有: 最大点权独立集 + 最小点权覆盖集 = 总点权和, 这个题很明显是要求 最大点权独立集 ,现在 总点权 已知,我们只要求出来 最小点权覆盖集 就好了,我们可以这样建图, 1,对矩阵中的点进行黑白着色(相邻的点颜色不同),从源点向黑色的点连一

P1004 方格取数

P1004 方格取数 题目描述 设有N*N的方格图(N<=9),我们将其中的某些方格中填入正整数,而其他的方格中则放 人数字0.如下图所示(见样例): A 0 0 0 0 0 0 0 0 0 0 13 0 0 6 0 0 0 0 0 0 7 0 0 0 0 0 0 14 0 0 0 0 0 21 0 0 0 4 0 0 0 0 15 0 0 0 0 0 0 14 0 0 0 0 0 0 0 0 0 0 0 0 0 0 . B 某人从图的左上角的A点出发,可以向下行走,也可以向右走,直到到达右下角