vijos 1563 疯狂的方格取数

P1653疯狂的方格取数

Accepted

标签:天才的talent[显示标签]

背景

Due to the talent of talent123,当talent123做完NOIP考了两次的二取方格数和vijos中的三取方格数后,突发奇想....

描述

在一个宽M,长N的矩阵中,请你编一个程序,n次从矩阵的左上角走到矩阵的右下角,每到一处,就取走该处的数字,请你选择一
种走法使取得的数字的和最大,并输出其最大值。其中:3<=M<=20 M<=N<=100 1<=n<=10

如输入数据:
3 10 13

0 1 2 3 4 9 7 1 3 1
9 1 2 2 3 6 7 8 1 2
1 2 3 4 5 9 8 7 6 1
9 7 1 3 1 9 1 2 2 3
6 7 8 1 2 1 2 3 4 5
9 1 2 2 3 6 7 8 1 2
1 2 3 4 5 9 8 7 6 1
9 7 1 3 1 9 1 2 2 3
6 7 8 1 2 1 2 3 4 5
9 1 2 2 3 6 7 8 1 2
1 2 3 4 5 9 8 7 6 1
9 7 1 3 1 9 1 2 2 3
6 7 8 1 2 1 2 3 4 0
其中n=3
M=10
N=13
即当n=3时,就相当于是3取方格数。

对于以上的数据:
将输出:297
//注:如过你想到了无记忆性搜所的方法(不管你怎样优化),你可以直接放弃这道题了。

//提示1:动态规划如果用的是二位数组,规模为100*100000即可。

//提示2:如果你坚信自己的程序已经无可优化了,可有2个数据依然超时,那么告诉你,存在数据有M<n的情况!!!

格式

输入格式

第一行:三个整数:n M N
以下的N行每行M个数字,代表你要处理的矩阵。

输出格式

只有一行:你所取得的数字的和。

样例1

样例输入1[复制]

4 6 7
0 2 3 4 5 6
6 5 4 3 2 1
0 9 8 7 6 5
12 3 4 5 6 7
0 0 0 1 2 3
12 23 34 45 1 23
4 5 6 6 1 0

样例输出1[复制]

265

限制

共有10个测试数据,每个测试数据包含1个测试点,每个测试点的时间限制为2秒钟。

来源

本题目来自:北京市,中关村中学,高三9班,孙一(网名:talent123

题解:

当年的难题如今终于轻松解决了……

不多说了,水题一道……

网络流想几道基本上就差不多了……

最大费用最大流

代码:

方法一:将费用取负

  1 uses math;
  2 const inf=maxlongint;
  3 type node=record
  4      from,go,next,v,c:longint;
  5      end;
  6 var e:array[0..200000] of node;
  7     pre,head,q,d:array[0..100000] of longint;
  8     v:array[0..100000] of boolean;
  9     num:array[0..100,0..100] of longint;
 10     i,j,n,s,t,l,r,mincost,tot,k,x,m:longint;
 11 procedure ins(x,y,z,w:longint);
 12  begin
 13  inc(tot);
 14  with e[tot] do
 15   begin
 16   from:=x;go:=y;v:=z;c:=w;next:=head[x];head[x]:=tot;
 17   end;
 18  end;
 19 procedure insert(x,y,z,w:longint);
 20  begin
 21  if y>100000 then exit;
 22  ins(x,y,z,w);ins(y,x,0,-w);
 23  end;
 24 function spfa:boolean;
 25  var i,x,y:longint;
 26  begin
 27  fillchar(v,sizeof(v),false);
 28  for i:=s to t do d[i]:=inf;
 29  l:=0;r:=1;q[1]:=s;d[s]:=0;v[s]:=true;
 30  while l<r do
 31   begin
 32   inc(l);
 33   x:=q[l];v[x]:=false;
 34   i:=head[x];
 35   while i<>0 do
 36    begin
 37    y:=e[i].go;
 38    if (e[i].v<>0) and (d[x]+e[i].c<d[y]) then
 39     begin
 40     d[y]:=d[x]+e[i].c;
 41     pre[y]:=i;
 42     if not(v[y]) then
 43      begin
 44      v[y]:=true;
 45      inc(r);
 46      q[r]:=y;
 47      end;
 48     end;
 49    i:=e[i].next;
 50   end;
 51  end;
 52  exit(d[t]<>inf);
 53  end;
 54 procedure mcf;
 55  var i,tmp:longint;
 56  begin
 57  mincost:=0;
 58  while spfa do
 59   begin
 60   tmp:=inf;
 61   i:=pre[t];
 62   while i<>0 do
 63    begin
 64    tmp:=min(tmp,e[i].v);
 65    i:=pre[e[i].from];
 66    end;
 67   inc(mincost,tmp*d[t]);
 68   i:=pre[t];
 69   while i<>0 do
 70    begin
 71    dec(e[i].v,tmp);
 72    inc(e[i xor 1].v,tmp);
 73    i:=pre[e[i].from];
 74    end;
 75   end;
 76  end;
 77 procedure init;
 78  begin
 79  tot:=1;
 80  readln(k,m,n);
 81  s:=0;t:=2*n*m+1;
 82  insert(s,1,k,0);insert(2*n*m,t,k,0);
 83  fillchar(num,sizeof(num),60);
 84  for i:=1 to n do for j:=1 to m do num[i,j]:=(i-1)*m+j;
 85  for i:=1 to n do
 86   begin
 87    for j:=1 to m do
 88     begin
 89      read(x);
 90      insert(num[i,j],num[i,j]+n*m,1,-x);
 91      insert(num[i,j],num[i,j]+n*m,inf,0);
 92      insert(num[i,j]+n*m,num[i+1,j],inf,0);
 93      insert(num[i,j]+n*m,num[i,j+1],inf,0);
 94     end;
 95   readln;
 96   end;
 97  end;
 98 procedure main;
 99  begin
100  mincost:=0;
101  mcf;
102  writeln(-mincost);
103  end;
104 begin
105  assign(input,‘input.txt‘);assign(output,‘output.txt‘);
106  reset(input);rewrite(output);
107  init;
108  if k=0 then writeln(0) else main;
109  close(input);close(output);
110 end.    

方法二:直接在spfa中把<改成>,其余一些预处理做修改

  1 uses math;
  2 const inf=maxlongint;
  3 type node=record
  4      from,go,next,v,c:longint;
  5      end;
  6 var e:array[0..200000] of node;
  7     pre,head,q,d:array[0..100000] of longint;
  8     v:array[0..100000] of boolean;
  9     num:array[0..100,0..100] of longint;
 10     i,j,n,s,t,l,r,mincost,tot,k,x,m:longint;
 11 procedure ins(x,y,z,w:longint);
 12  begin
 13  inc(tot);
 14  with e[tot] do
 15   begin
 16   from:=x;go:=y;v:=z;c:=w;next:=head[x];head[x]:=tot;
 17   end;
 18  end;
 19 procedure insert(x,y,z,w:longint);
 20  begin
 21  if y>100000 then exit;
 22  ins(x,y,z,w);ins(y,x,0,-w);
 23  end;
 24 function spfa:boolean;
 25  var i,x,y:longint;
 26  begin
 27  fillchar(v,sizeof(v),false);
 28  for i:=s to t do d[i]:=-1;
 29  l:=0;r:=1;q[1]:=s;d[s]:=0;v[s]:=true;
 30  while l<r do
 31   begin
 32   inc(l);
 33   x:=q[l];v[x]:=false;
 34   i:=head[x];
 35   while i<>0 do
 36    begin
 37    y:=e[i].go;
 38    if (e[i].v<>0) and (d[x]+e[i].c>d[y]) then
 39     begin
 40     d[y]:=d[x]+e[i].c;
 41     pre[y]:=i;
 42     if not(v[y]) then
 43      begin
 44      v[y]:=true;
 45      inc(r);
 46      q[r]:=y;
 47      end;
 48     end;
 49    i:=e[i].next;
 50   end;
 51  end;
 52  exit(d[t]<>-1);
 53  end;
 54 procedure mcf;
 55  var i,tmp:longint;
 56  begin
 57  mincost:=0;
 58  while spfa do
 59   begin
 60   tmp:=inf;
 61   i:=pre[t];
 62   while i<>0 do
 63    begin
 64    tmp:=min(tmp,e[i].v);
 65    i:=pre[e[i].from];
 66    end;
 67   inc(mincost,tmp*d[t]);
 68   i:=pre[t];
 69   while i<>0 do
 70    begin
 71    dec(e[i].v,tmp);
 72    inc(e[i xor 1].v,tmp);
 73    i:=pre[e[i].from];
 74    end;
 75   end;
 76  end;
 77 procedure init;
 78  begin
 79  tot:=1;
 80  readln(k,m,n);
 81  s:=0;t:=2*n*m+1;
 82  insert(s,1,k,0);insert(2*n*m,t,k,0);
 83  fillchar(num,sizeof(num),60);
 84  for i:=1 to n do for j:=1 to m do num[i,j]:=(i-1)*m+j;
 85  for i:=1 to n do
 86   begin
 87    for j:=1 to m do
 88     begin
 89      read(x);
 90      insert(num[i,j],num[i,j]+n*m,1,x);
 91      insert(num[i,j],num[i,j]+n*m,inf,0);
 92      insert(num[i,j]+n*m,num[i+1,j],inf,0);
 93      insert(num[i,j]+n*m,num[i,j+1],inf,0);
 94     end;
 95   readln;
 96   end;
 97  end;
 98 procedure main;
 99  begin
100  mincost:=0;
101  mcf;
102  writeln(mincost);
103  end;
104 begin
105  assign(input,‘input.txt‘);assign(output,‘output.txt‘);
106  reset(input);rewrite(output);
107  init;
108  if k=0 then writeln(0) else main;
109  close(input);close(output);
110 end.
111          

vijos 1563 疯狂的方格取数

时间: 2024-11-15 18:19:57

vijos 1563 疯狂的方格取数的相关文章

Vijos1653 疯狂的方格取数(MCMF)

题意: 给出一个方格取数,最多能取k次,问最多能取到多少 思路: 最大费用最大流 #include<cstring> #include<iostream> #include<algorithm> #include<queue> #include<vector> #include<set> #include<cmath> #include<stack> #define ll long long using nam

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点出发,可以向下行走,也可以向右走,直到到达右下角

hdoj 1569 方格取数(2) 【最小割】 【最大点权独立集】

方格取数(2) Time Limit: 10000/5000 MS (Java/Others)    Memory Limit: 65536/32768 K (Java/Others) Total Submission(s): 5589    Accepted Submission(s): 1741 Problem Description 给你一个m*n的格子的棋盘,每个格子里面有一个非负数. 从中取出若干个数,使得任意的两个数所在的格子没有公共边,就是说所取数所在的2个格子不能相邻,并且取出的

1475: 方格取数

1475: 方格取数 Time Limit: 5 Sec  Memory Limit: 64 MBSubmit: 578  Solved: 309[Submit][Status][Discuss] Description 在一个n*n的方格里,每个格子里都有一个正整数.从中取出若干数,使得任意两个取出的数所在格子没有公共边,且取出的数的总和尽量大. Input 第一行一个数n:(n<=30) 接下来n行每行n个数描述一个方阵 Output 仅一个数,即最大和 Sample Input 2 1 2

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

方格取数(2) Time Limit: 10000/5000 MS (Java/Others)    Memory Limit: 65536/32768 K (Java/Others) Total Submission(s): 5146    Accepted Submission(s): 1610 Problem Description 给你一个m*n的格子的棋盘,每个格子里面有一个非负数. 从中取出若干个数,使得任意的两个数所在的格子没有公共边,就是说所取数所在的2个格子不能相邻,并且取出的

HDU 1565 方格取数(1) (状态压缩 DP)

方格取数(1) Time Limit: 10000/5000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others) Total Submission(s): 5779    Accepted Submission(s): 2194 Problem Description 给你一个n*n的格子的棋盘,每个格子里面有一个非负数. 从中取出若干个数,使得任意的两个数所在的格子没有公共边,就是说所取的数所在的2个格子不能相邻,并且取出

HDU 1565 方格取数(1)(状压dp)

感觉这道题目的数据比较水啊,程序的时间复杂度为1711^2*20竟然也可以过掉....其他的就是状压了啊,注意需要滚动一下啊.... 方格取数(1) Time Limit: 10000/5000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others) Total Submission(s): 5701    Accepted Submission(s): 2159 Problem Description 给你一个n*n的格子的棋

hdu 3657 最小割的活用 / 奇偶方格取数类经典题 /最小割

题意:方格取数,如果取了相邻的数,那么要付出一定代价.(代价为2*(X&Y))(开始用费用流,敲升级版3820,跪...) 建图:  对于相邻问题,经典方法:奇偶建立二分图.对于相邻两点连边2*(X&Y),源->X连边,Y->汇连边,权值w为点权. ans=总点权-最小割:如果割边是源->X,表示x不要选(是割边,必然价值在路径上最小),若割边是Y-汇点,同理:若割边是X->Y,则表示选Y点且选X点, 割为w( 2*(X&Y) ). 自己的确还没有理解其本质