4777: 方格取数 

Time Limit(Common/Java):1000MS/3000MS     Memory Limit:65536KByte
Total Submit: 11            Accepted:10

Description

设有N*N的方格图(N<=10,我们将其中的某些方格中填入正整数,而其他的方格中则放入数字0。如下图所示(见样例):

某人从图的左上角的A 点出发,可以向下行走,也可以向右走,直到到达右下角的B点。在走过的路上,他可以取走方格中的数(取走后的方格中将变为数字0)。

此人从A点到B 点共走两次,试找出2条这样的路径,使得取得的数之和为最大。

Input

输入的第一行为一个整数N(表示N*N的方格图),接下来的每行有三个整数,前两个表示位置,第三个数为该位置上所放的数。一行单独的0表示输入结束。

Output

只需输出一个整数,表示2条路径上取得的最大的和。

Sample Input

8
2 3 13
2 6 6
3 5 7
4 4 14
5 2 21
5 6 4
6 3 15
7 2 14
0 0 0

Sample Output

67

我觉得大家第一反应应该都是做一次DP之后再做一次,但是这是在贪心,这次走完最大值的路径下次就不走了

所以其实要一起考虑,算法复杂度是n^3,它是有四个点的,包括前一次经过的点,而且步数的几个点是确定的,在一条斜线上

#include <bits/stdc++.h>
using namespace std;
#define max4(a, b, c, d) max(max(a, b), max(c, d))
int dp[][][];
int a[][];
int main()
{
int n, x, y, z;
scanf("%d", &n);
while (~scanf("%d%d%d", &x, &y, &z) && (x || y || z))a[x][y] = z;
for (int k = ; k < n * ; k++)
for (int i = ; i <= n; i++)
for (int j = ; j <= n; j++)
{
if (i > k || j > k || k - j + > n || k - i + > n)continue;
dp[k][i][j] = max4(dp[k - ][i][j], dp[k - ][i - ][j], dp[k - ][i][j - ], dp[k - ][i - ][j - ]);
dp[k][i][j] += a[k - j + ][j];
if (i != j)dp[k][i][j] += a[k - i + ][i];
}
cout << dp[n * - ][n][n];
return ;
}

升级版的k步,需要使用最大流求解

首先拆点,将一个点拆成x和y,然后从x到y连一条容量为1,流量为x的边

然后再连一条容量为inf,费用为0的边

这样即可保证一个点可以走多次,而数只能取一次。然后连接a和b时,从a的y向b的x连一条容量为inf,费用为0的边。最后跑最大费用最大流即可。

#include <bits/stdc++.h>
using namespace std; const int N = 1e4 + ;
const int M = 1e5 + ;
const int INF = 0x3f3f3f3f; int FIR[N], TO[M], CAP[M], FLOW[M], COST[M], NEXT[M], tote;
int pre[N], dist[N], q[];
bool vis[N];
int n, k, S, T;
void init()
{
tote = ;
memset(FIR, -, sizeof(FIR));
}
void add(int u, int v, int cap, int cost)
{
TO[tote] = v;
CAP[tote] = cap;
FLOW[tote] = ;
COST[tote] = cost;
NEXT[tote] = FIR[u];
FIR[u] = tote++; TO[tote] = u;
CAP[tote] = ;
FLOW[tote] = ;
COST[tote] = -cost;
NEXT[tote] = FIR[v];
FIR[v] = tote++;
}
bool SPFA(int s, int t)
{
memset(dist, INF, sizeof(dist));
memset(vis, false, sizeof(vis));
memset(pre, -, sizeof(pre));
dist[s] = ;
vis[s] = true;
q[] = s;
int head = , tail = ;
while (head != tail)
{
int u = q[++head];
vis[u] = false;
for (int v = FIR[u]; v != -; v = NEXT[v])
{
if (dist[TO[v]] > dist[u] + COST[v] && CAP[v] > FLOW[v])
{
dist[TO[v]] = dist[u] + COST[v];
pre[TO[v]] = v;
if (!vis[TO[v]])
{
vis[TO[v]] = true;
q[++tail] = TO[v];
}
}
}
}
return pre[t] != -;
}
void MCMF(int s, int t, int &cost, int &flow)
{
flow = cost = ;
while (SPFA(s, t))
{
int Min = INF;
for (int v = pre[t]; v != -; v = pre[TO[v ^ ]])
Min = min(Min, CAP[v] - FLOW[v]);
for (int v = pre[t]; v != -; v = pre[TO[v ^ ]])
{
FLOW[v] += Min;
FLOW[v ^ ] -= Min;
cost += COST[v] * Min;
}
flow += Min;
}
}
int main()
{
int ca;
cin>>ca;
while(ca--)
{
init();
cin >> n >> k;
S = ;
T = n * n * + ;
int ff=n*n;
for (int i = ; i <= n; i++)
for (int j = , x; j <= n; j++)
{
cin>>x;
int a=(i-)*n+j,b=a+,c=a+n;
add(a,ff+a,INF,),add(a,ff+a,,-x);
if(j<n)add(ff+a,b,INF,);
if(i<n)add(ff+a,c,INF,);
}
add(S, , k, );
add(T - , T, k, );
int cost, flow;
MCMF(S, T, cost, flow);
printf("%d\n", -cost);
}
return ;
}

TZOJ4777: 方格取数的更多相关文章

  1. HDU 1565&1569 方格取数系列(状压DP或者最大流)

    方格取数(2) Time Limit: 10000/5000 MS (Java/Others)    Memory Limit: 65536/32768 K (Java/Others) Total S ...

  2. NOIP200003方格取数

    NOIP200003方格取数 难度级别: D: 编程语言:不限:运行时间限制:1000ms: 运行空间限制:51200KB: 代码长度限制:2000000B 试题描述 XYZ 是首师大附中信息技术团编 ...

  3. vijos 1563 疯狂的方格取数

    P1653疯狂的方格取数 Accepted 标签:天才的talent[显示标签]   背景 Due to the talent of talent123,当talent123做完NOIP考了两次的二取 ...

  4. [HDU 1565+1569] 方格取数

    HDU 1565 方格取数(1) Time Limit: 10000/5000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others ...

  5. 网络流(最大流) HDU 1565 方格取数(1) HDU 1569 方格取数(2)

      HDU 1565 方格取数(1) 给你一个n*n的格子的棋盘,每个格子里面有一个非负数.从中取出若干个数,使得任意的两个数所在的格子没有公共边,就是说所取的数所在的2个格子不能相邻,并且取出的数的 ...

  6. HDU-1565 方格取数(1)

    http://acm.hdu.edu.cn/showproblem.php?pid=1565 方格取数(1) Time Limit: 10000/5000 MS (Java/Others)    Me ...

  7. BZOJ 1475: 方格取数( 网络流 )

    本来想写道水题....结果调了这么久!就是一个 define 里面少加了个括号 ! 二分图最大点权独立集...黑白染色一下 , 然后建图 : S -> black_node , white_no ...

  8. [动态规划]P1004 方格取数

    ---恢复内容开始--- 题目描述 设有N*N的方格图(N<=9),我们将其中的某些方格中填入正整数,而其他的方格中则放 人数字0.如下图所示(见样例): A 0 0 0 0 0 0 0 0 0 ...

  9. P2045 方格取数加强版

    P2045 方格取数加强版 题目描述 给出一个n*n的矩阵,每一格有一个非负整数Aij,(Aij <= 1000)现在从(1,1)出发,可以往右或者往下走,最后到达(n,n),每达到一格,把该格 ...

随机推荐

  1. angularjs中动态为audio绑定src问题总结

    先上代码 <div class="block_area block_audio" ng-show="model.url"> <audio co ...

  2. 软件-DiskSpeekUp:DiskSpeekUp(磁盘整理工具)

    ylbtech-软件-DiskSpeekUp:DiskSpeekUp(磁盘整理工具) Disk SpeedUP是一个完全自由和极快的碎片整理工具来分析,碎片整理和优化计算机性能的峰值磁盘. 它是安全没 ...

  3. DVWA 之low级别sql注入

    将Security level设为low,在左侧列表中选择“SQL Injection”,然后在右侧的“User ID”文本框中输入不同的数字就会显示相应的用户信息. 我们首先需要判断这里所传输的参数 ...

  4. [转载] DSP6000图像位移与变形典型算法

    原文地址:转载:DSP6000图像位移与变形典型算法作者:Jane 李现路:DSP6000图像位移与变形典型算法 一.图像的平移算法 图像平移的数学表达式原理: 初始坐标为(x0,y0)的点经过平移( ...

  5. IO流16 --- 对象流操作字符串 --- 技术搬运工(尚硅谷)

    序列化 @Test public void test12() throws IOException { ObjectOutputStream oos = new ObjectOutputStream( ...

  6. 关于python中 and 和 or 的一些特殊使用

    print(True or 1)  # True print(1 or True) # 1 print(3 or 1) # 3 print(0 or 3) # 3 总结:or左边无论是 数字还是Boo ...

  7. spring boot 源码解析11-ConfigurationClassPostProcessor类加载解析

    前言 ConfigurationClassPostProcessor实现了BeanDefinitionRegistryPostProcessor接口,该类会在AbstractApplicationCo ...

  8. 解决导入TensorFlow后出现警告的的问题解决:通过降低numpy的版本

    在原有基础上安装tensorflow 重新虚拟出一个环境安装tensorflow 安装 测试 大多教程都是重新虚拟出一个环境,原有环境就可以支持为什么还要重建一个新的环境,如果以后遇到坑了更新解释. ...

  9. TZOJ 4267 An Easy Puz(深搜)

    描述 Wddpdh find an interesting mini-game in the BBS of WHU, called “An easy PUZ”. It’s a 6 * 6 chess ...

  10. spotbus gradle-qulity-plugiin 多项目bug检查

    https://spotbugs.readthedocs.io/en/latest/bugDescriptions.html https://xvik.github.io/gradle-quality ...