HDU 2686 (双线程) Matrix

这也是当初卡了很久的一道题

题意:从左上角的格子出发选一条路径到右上角然后再回到左上角,而且两条路径除了起点和终点不能有重合的点。问所经过的格子中的最大和是多少

状态设计:我们可以认为是从左上角出发了两条路径,然后同时到达右下角。容易看出,第k个阶段所有可能到达的格子构成一条斜线而且满足x1 + y1 = x2 + y2 = k + 1

dp[k][x1][x2]表示第k阶段两条路分别到达(x1, y1) (x2, y2)所能取得的最大值(y1 y2根据上面的等量关系来计算),如果x1 = x2表示两条路径汇合于一点了

状态转移方程:

在求解第k阶段最优解时,首先枚举k-1阶段时的状态(x1‘, x2‘),然后向四个方向延伸出(x1, x2)

dp[k][x1][x2] = max{dp[k-1][x1‘][x2‘] + num[x1][y1] | (x1=x2),  dp[k-1][x1‘][x2‘] + num[x1][y1] + num[x2][y2] | (x1≠x2)}

在循环的过程中可能会出现从一个点延伸的下一个点的情况,即两条路径可能重合,不过不要紧,因为格子里面都是正数,所以得到的最优解一定是两条不重合的路径

优化:

因为两条路径具有任意性,所以不妨规定第一条路在第二条路的下方(或同一水平线),时间从92MS优化到62MS

第k阶段状态的转移只依赖第k-1阶段的状态,可以用滚动数组(由于原来的空间本不大,所以代码中没有实现滚动数组)

 1 //#define LOCAL
 2 #include <iostream>
 3 #include <cstdio>
 4 #include <cstring>
 5 using namespace std;
 6
 7 int dp[70][35][35], num[35][35], n;
 8
 9 bool islegal(int x, int y)
10 {
11     return (x>=1 && x<=n && y>=1 && y<=n);
12 }
13
14 int main(void)
15 {
16     #ifdef LOCAL
17         freopen("2686in.txt", "r", stdin);
18     #endif
19
20     int i, j, k, d1, d2, x1, x2, y1, y2;
21     while(scanf("%d", &n) == 1)
22     {
23         memset(dp, 0, sizeof(dp));
24         for(i = 1; i <= n; ++i)
25             for(j = 1; j <= n; ++j)
26                 scanf("%d", &num[i][j]);
27
28         dp[1][1][1] = num[1][1];
29         for(k = 2; k <= 2*n-1; ++k)
30         {
31             for(i = 1; i <= k - 1; ++i)
32                 for(j = 1; j <= i; ++j)
33                 {//枚举两条路径在k-1步时的状态
34                     for(d1 = 0; d1 <= 1; ++d1)
35                         for(d2 = 0; d2 <= 1; ++d2)
36                         {//共四个延伸方向
37                             x1 = i + d1, y1 = k + 1 - x1;
38                             x2 = j + d2, y2 = k + 1 - x2;
39                             if(islegal(x1, y1) && islegal(x2, y2))
40                             {
41                                 if(x1 == x2)
42                                     dp[k][x1][x2] = max(dp[k][x1][x2], dp[k-1][i][j] + num[x1][y1]);
43                                 else
44                                     dp[k][x1][x2] = max(dp[k][x1][x2], dp[k-1][i][j] + num[x1][y1] + num[x2][y2]);
45                             }
46                         }
47                 }
48         }
49         printf("%d\n", dp[2*n-1][n][n]);
50     }
51     return 0;
52 }

代码君

时间: 2024-11-10 01:33:21

HDU 2686 (双线程) Matrix的相关文章

hdu 2686 费用流 / 双线程DP

题意:给一个方阵,求从左上角出到右下角(并返回到起点),经过每个点一次不重复,求最大获益(走到某处获得改点数值),下来时每次只能向右或向下,反之向上或向左. 俩种解法: 1  费用流法:思路转化:从左上角流出2的流量,(表示走俩条路),归于右下角,可以走就有边(右和下),权为负的费用,源点连起点,汇点连终点,流量为2. 除源汇外所有点一分为2,Y向X对应点有流量1的边,之前边为X到Y的(原图),这样处理解决每个点只最多走一次(除了源汇外)(X部只出,Y部要出必先回到X对应点).跑最小费用最大流即

POJ 2135 Farm Tour &amp;&amp; HDU 2686 Matrix &amp;&amp; HDU 3376 Matrix Again 费用流求来回最短路

累了就要写题解,最近总是被虐到没脾气. 来回最短路问题貌似也可以用DP来搞,不过拿费用流还是很方便的. 可以转化成求满流为2 的最小花费.一般做法为拆点,对于 i 拆为2*i 和 2*i+1,然后连一条流量为1(花费根据题意来定) 的边来控制每个点只能通过一次. 额外添加source和sink来控制满流为2. 代码都雷同,以HDU3376为例. #include <algorithm> #include <iostream> #include <cstring> #in

HDU 2686 Matrix(最大费用最大流+拆点)

题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=2686 和POJ3422一样 删掉K把汇点与源点的容量改为2(因为有两个方向的选择)即可 #include <iostream> #include <cstdlib> #include <cstdio> #include <cstring> #include <queue> #include <algorithm> const int ma

HDU 2686 Matrix 3376 Matrix Again(费用流)

HDU 2686 Matrix 题目链接 3376 Matrix Again 题目链接 题意:这两题是一样的,只是数据范围不一样,都是一个矩阵,从左上角走到右下角在从右下角走到左上角能得到最大价值 思路:拆点,建图,然后跑费用流即可,不过HDU3376这题,极限情况是300W条边,然后卡时间过了2333 代码: #include <cstdio> #include <cstring> #include <vector> #include <queue> #i

hdu 2686 Matrix &amp;&amp; hdu 3367 Matrix Again (最大费用最大流)

Matrix Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others)Total Submission(s): 1394    Accepted Submission(s): 758 Problem Description Yifenfei very like play a number game in the n*n Matrix. A positive integer number

hdu1007 平面最近点对(暴力+双线程优化)

突发奇想,用双线程似乎可以优化一些暴力 比如说平面最近点对这个题目,把点复制成2份 一份按照x排序,一份按照y排序 然后双线程暴力处理,一份处理x,一份处理y 如果数据利用x递减来卡,那么由于双线程,它卡不住y 如果数据利用y递减来卡,那么卡不住x 这样暴力n^2就可以过了 #include <iostream> #include <cstdio> #include <cstring> #include <cmath> #include <algori

多线程十大经典案例之一 双线程读写队列数据

本文配套程序下载地址为:http://download.csdn.net/detail/morewindows/5136035 转载请标明出处,原文地址:http://blog.csdn.net/morewindows/article/details/8646902 欢迎关注微博:http://weibo.com/MoreWindows 在<秒杀多线程系列>的前十五篇中介绍多线程的相关概念,多线程同步互斥问题<秒杀多线程第四篇一个经典的多线程同步问题>及解决多线程同步互斥的常用方法

秒杀多线程第十六篇 多线程十大经典案例之一 双线程读写队列数据

版权声明:本文为博主原创文章,未经博主允许不得转载. 目录(?)[+] 本文配套程序下载地址为:http://download.csdn.net/detail/morewindows/5136035 转载请标明出处,原文地址:http://blog.csdn.net/morewindows/article/details/8646902 欢迎关注微博:http://weibo.com/MoreWindows 在<秒杀多线程系列>的前十五篇中介绍多线程的相关概念,多线程同步互斥问题<秒杀多

蓝桥杯 - 传纸条 (双线程DP)

题目传送:传纸条 思路:双线程DP,具体看代码; AC代码: #include <map> #include <set> #include <cmath> #include <deque> #include <queue> #include <stack> #include <cstdio> #include <cctype> #include <string> #include <vecto