Codeforces 429B Working out:dp【枚举交点】

题目链接:http://codeforces.com/problemset/problem/429/B

题意:

  给你一个n*m的网格,每个格子上有一个数字a[i][j]。

  一个人从左上角走到右下角,一个人从左下角走到右上角,要求两条路径有且仅有一个交点。

  问你除去交点格子上的数字,路径上数字之和最大是多少。

 

题解:

  表示状态:

    dp[i][j][0/1/2/3] = max sum

    表示从某个角走到(i,j)这个格子,最大路径上数字之和

    0,1,2,3分别代表左上角、右上角、左下角、右下角

 

  找出答案:

    路径相交共有两种方式:

    

    枚举交点(i,j)。

    ans = max dp[i-1][j][0] + dp[i+1][j][3] + dp[i][j-1][2] + dp[i][j+1][1]

    ans = max dp[i-1][j][1] + dp[i+1][j][2] + dp[i][j-1][0] + dp[i][j+1][3]

 

  如何转移:

    四种情况分别算:

    (1)dp[i][j][0] = max dp[i-1][j][0]+a[i][j]

       dp[i][j][0] = max dp[i][j-1][0]+a[i][j]

    (2)dp[i][j][1] = max dp[i-1][j][1]+a[i][j]

       dp[i][j][1] = max dp[i][j+1][1]+a[i][j]

    (3)dp[i][j][2] = max dp[i+1][j][2]+a[i][j]

       dp[i][j][2] = max dp[i][j-1][2]+a[i][j]

    (4)dp[i][j][3] = max dp[i+1][j][3]+a[i][j]

       dp[i][j][3] = max dp[i][j+1][3]+a[i][j]

 

  边界条件:

    set dp = 0

 

AC Code:

 1 #include <iostream>
 2 #include <stdio.h>
 3 #include <string.h>
 4 #define MAX_N 1005
 5 
 6 using namespace std;
 7 
 8 int n,m;
 9 int a[MAX_N][MAX_N];
10 int dp[MAX_N][MAX_N][4];
11 
12 void read()
13 {
14     cin>>n>>m;
15     for(int i=1;i<=n;i++)
16     {
17         for(int j=1;j<=m;j++)
18         {
19             cin>>a[i][j];
20         }
21     }
22 }
23 
24 void work()
25 {
26     memset(dp,0,sizeof(dp));
27     for(int i=1;i<=n;i++)
28     {
29         for(int j=1;j<=m;j++)
30         {
31             dp[i][j][0]=max(dp[i][j][0],dp[i-1][j][0]+a[i][j]);
32             dp[i][j][0]=max(dp[i][j][0],dp[i][j-1][0]+a[i][j]);
33         }
34     }
35     for(int i=1;i<=n;i++)
36     {
37         for(int j=m;j>=1;j--)
38         {
39             dp[i][j][1]=max(dp[i][j][1],dp[i-1][j][1]+a[i][j]);
40             dp[i][j][1]=max(dp[i][j][1],dp[i][j+1][1]+a[i][j]);
41         }
42     }
43     for(int i=n;i>=1;i--)
44     {
45         for(int j=1;j<=m;j++)
46         {
47             dp[i][j][2]=max(dp[i][j][2],dp[i+1][j][2]+a[i][j]);
48             dp[i][j][2]=max(dp[i][j][2],dp[i][j-1][2]+a[i][j]);
49         }
50     }
51     for(int i=n;i>=1;i--)
52     {
53         for(int j=m;j>=1;j--)
54         {
55             dp[i][j][3]=max(dp[i][j][3],dp[i+1][j][3]+a[i][j]);
56             dp[i][j][3]=max(dp[i][j][3],dp[i][j+1][3]+a[i][j]);
57         }
58     }
59     int ans=0;
60     for(int i=2;i<n;i++)
61     {
62         for(int j=2;j<m;j++)
63         {
64             ans=max(ans,dp[i-1][j][0]+dp[i+1][j][3]+dp[i][j-1][2]+dp[i][j+1][1]);
65             ans=max(ans,dp[i-1][j][1]+dp[i+1][j][2]+dp[i][j-1][0]+dp[i][j+1][3]);
66         }
67     }
68     cout<<ans<<endl;
69 }
70 
71 int main()
72 {
73     read();
74     work();
75 }

 

posted @ 2018-01-04 10:12  Leohh  阅读(186)  评论(0编辑  收藏  举报