Friday, December 16, 2011

A grid of size N rows and M columns is filled with numbers, one in each cell. You start at the centre of the cell at the top-left corner (1,1) and your destination is the centre of the cell at the bottom-right corner(N,M). In each step, you are only allowed to move to the centre of the cell to the right or to the centre of the cell to the bottom. There are many paths you can take to reach your destination from your start – however, every path can be uniquely broken down into a series of straight line-segments joined at right-angles. Each straight line-segment in your path is termed a ‘leg’ of your path.
Your task is to choose a subset of the cells along your path in such a way that the sum of the numbers in the chosen cells is maximized. Your choice of cells must be such that exactly one chosen cell is present on each leg of the path. Note that cells at the intersection of two legs belong to both legs. What is the maximum possible sum you can form?
Input Format:
The first line contains one integer T, the number of testcases. The first line of each test case contains two space-separated integers N and M. Each of the next N lines contains M space separated integers, denoting cell values. The jth integer in the ith line denotes the value of the cell (i, j).
Constraints:
1 <= T <= 10
1 <= N, M <= 100
Numbers in each cell will be between -10000 and 10000 inclusive.
Output Format:
For each testcase output a single line containing the maximum sum you can form.
Sample Input:
3
2 2
-1 -2
5 -1
3 4
-1 2 -3 -4
-2 -3 5 -2
-1 -1 -2 3
2 2
3 1
5 3
Sample Output:
5
10
6
Explanation:
In the first test case, you can first move down and then move right. Your path now has 2 legs and you can choose only the cell containing 5. This is valid as it satisfies the condition that you must choose exactly one cell in each leg (because 5 is a part of both legs).
In the second test case, one best path is to walk right, choose 2, go right again and then down to choose 5, go further down and then right to pick up the final 3 (There are also other ways to pick-up the same numbers).
In the third test case, the best path is either (down, right) or (right, down). Note that since you can pick-up only one number in each leg you cannot select the ’5′ in the lower left corner (If you decide to pick-up 5, then you cannot pick up any other number because ’5′ is shared by both legs. We can do better by selecting both 3s).
Time limit: 2 seconds
Memory: 64 MB
ACM International Collegiate Programming Contest, 2010, Asia-Amritapuri Site
Solution ( Source : Team Imperials )

01/***** Author : Kunal *****/
02#include <iostream>
03#include <cmath>
04#include <cstdio>
05using namespace std;
06 
07#define REP(a,b) for(int a=0;a<b;a++)
08#define FOR(a,b,c) for(int a=b;a<c;a++)
09#define FORD(a,b,c) for(int a=b;a>=c;a--)
10 
11#define S scanf
12#define P printf
13 
14#define INF 1000000000
15 
16int A[102][102];
17int rmax[102][102][102];
18int cmax[102][102][102];
19int n, m;
20 
21void findRowMax()
22{
23    REP(i, n ) REP(j, m ) REP(k, m ) rmax[i][j][k] = -INF;
24    REP(i, n )
25    {
26        REP(j, m )
27        {
28            rmax[i][j][j] = A[i][j];
29            FOR(k, j+1, m ) rmax[i][j][k] = max( rmax[i][j][k-1], A[i][k] );
30        }
31    }
32}
33 
34void findColMax()
35{
36    REP(i, m ) REP(j, n ) REP(k, n ) cmax[i][j][k] = -INF;
37    REP(i, m )
38    {
39        REP(j, n )
40        {
41            cmax[i][j][j] = A[j][i];
42            FOR(k, j+1, n ) cmax[i][j][k] = max( cmax[i][j][k-1], A[k][i] );
43        }
44    }
45}
46int dp[102][102][2][2];
47int main()
48{
49    int t; S("%d", &t );
50    while( t-- )
51    {
52        S("%d%d", &n, &m );
53        REP(i, n ) REP(j, m ) S("%d", &A[i][j] );
54        findRowMax(); findColMax();
55        REP(i, n ) REP(j, m ) REP(k,2)  dp[i][j][k][0] = dp[i][j][k][1] = -INF;
56        REP(i, m )
57        {
58            if( i-1 >= 0 ) dp[0][i][0][0]  = rmax[0][0][i-1];
59            dp[0][i][0][1] = A[0][i];
60        }
61        REP(i, n )
62        {
63            if( i-1 >= 0 ) dp[i][0][1][0]  = cmax[0][0][i-1];
64            dp[i][0][1][1] = A[i][0];
65        }
66        FOR(i, 1, n )
67        {
68            FOR(j, 1, m )
69            {
70                REP(k, j )
71                {
72                    dp[i][j][0][0] = max( dp[i][j][0][0], dp[i][k][1][0] + rmax[ i][ k+1][ j-1]  );
73                    dp[i][j][0][0] = max( dp[i][j][0][0], dp[i][k][1][1] );
74                    dp[i][j][0][1] = max( dp[i][j][0][1], dp[i][k][1][0] + A[i][j] );
75                }
76                REP(k, i )
77                {
78                    dp[i][j][1][0] = max( dp[i][j][1][0], dp[k][j][0][0] + cmax[ j][ k+1][ i-1]  );
79                    dp[i][j][1][0] = max( dp[i][j][1][0], dp[k][j][0][1] );
80                    dp[i][j][1][1] = max( dp[i][j][1][1], dp[k][j][0][0] + A[i][j] );
81                }
82            }
83        }
84        int Ans = -INF;
85        REP(i, 2 ) REP(j,2) Ans = max( Ans, dp[n-1][m-1][i][j] );
86        P("%d\n", Ans );
87    }
88    return 0;
89}

No comments :