• 棋盘型动态规划 之 CODE[VS] 1169 传纸条 2008年NOIP全国联赛提高组


    /*
    这道题要解决两个问题
    	1)状态和状态方程
    	2)怎么保证每走一步,所形成的路径不相交,以保证最后生成的完整路径不相交。
     
     
    (1)状态:
    dp[i][j][k][l] = 小渊传递的纸条到[i][j]的位置,小轩传递的纸条到[k][l]的位置时,好心程度和的最大值。
     
     
    (2)状态方程:
    看到题目,直接的想法是:
    按题意,小渊从左上角->右下角,小轩从右下角->左上角。但是,路径在走的时候,怎么才能保证路径不相交,我想不出来办法了。。。
     
    仔细想,题目要求:
    两条路径的头尾坐标相同(出发点选择不同),但实际上选择头或尾哪个点作为出发点,都是无所谓的。
    那么就让两条路径都从点[1][1]出发,此种做法有比较简单的办法保证路径不相交。
     
    dp[i][j][k][l] = arr[i][j] + arr[k][l] +
    		max{dp[i-1][j][k-1][l], dp[i-1][j][k][l-1], dp[i][j-1][k-1][l], dp[i][j-1][k][l-1]}
     
     
    (3)控制条件(保证获得不相交的路径):
    两条路径都从点[1][1]出发,让两条路径并行去走,并保证小渊走到点[i][j],小轩走到[k][l]时,所形成的路径不相交:
    	关键: 
    		1) 并行 (i+j)=(k+l)
    		2) 不相交 if (i==k)&&(j==l) return false;
     
    (4)得到答案:
    两条路径要想到达点[m][n],则两条路径选择到达目的地的点必然选择:[m][n-1],[m-1][n]
    (因为到达目的地,只有两种动作:向下,向左)
    故:ans = max(dp[m][n - 1][m - 1][n], dp[m - 1][n][m][n-1])
    */
      1 #define _CRTDBG_MAP_ALLOC
      2 #include <stdlib.h>
      3 #include <crtdbg.h>
      4 void fnExit1(void)
      5 {
      6     _CrtDumpMemoryLeaks();
      7 }
      8 
      9 #define _CRT_SECURE_NO_WARNINGS
     10 #define HOME
     11 
     12 #include <iostream>
     13 #include <cstdlib>
     14 #include <cstdio>
     15 #include <cstddef>
     16 #include <iterator>
     17 #include <algorithm>
     18 #include <locale>
     19 #include <cmath>
     20 #include <vector>
     21 #include <cstring>
     22 using namespace std;
     23 const int INF = 0x3f3f3f3f;
     24 const int MaxN = 30;
     25 const int Max = 55;
     26 
     27 int m, n;
     28 int arr[Max][Max];
     29 int dp[Max][Max][Max][Max];
     30 int step[2][2] = { {-1, 0}, {0, -1} }; // 向下,向左
     31 
     32 bool Check(int x1, int y1, int x2, int y2)
     33 {
     34     // 防止越界
     35     if ((x1 <= 0) || (y1 <= 0) || (x2 <= 0) || (y2 <= 0))
     36     {
     37         return false;
     38     }
     39     // 两条路径不能相交
     40     if ((x1 == x2) && (y1 == y2))
     41     {
     42         return false;
     43     }
     44     return true;
     45 }
     46 
     47 void Solve()
     48 {
     49     int x1, y1, x2, y2;
     50     for (int i = 1; i <= m; ++i)
     51     {
     52         for (int j = 1; j <= n; ++j)
     53         {
     54             for (int k = 1; k <= m; ++k)
     55             {
     56 
     57                 // 两条路径并行走,则:(i+j)=(k+l)
     58                 if (i + j - k <= 0) break;
     59                 int l = i + j - k;
     60                 if (!Check(i, j, k, l)) continue;
     61                 int maxVal = 0;
     62                 for (int p = 0; p < 2; ++p)
     63                 {
     64                     for (int q = 0; q < 2; ++q)
     65                     {
     66                         x1 = i + step[p][0];
     67                         y1 = j + step[p][1];
     68                         x2 = k + step[q][0];
     69                         y2 = l + step[q][1];
     70                         if (Check(x1, y1, x2, y2))
     71                         {
     72                             maxVal = max(maxVal, dp[x1][y1][x2][y2]);
     73                         }
     74                     }
     75                 }
     76                 dp[i][j][k][l] = max(dp[i][j][k][l], maxVal + arr[i][j] + arr[k][l]);
     77             }
     78         }
     79     }
     80     // 两条路径要想到达点[m][n],则两条路径的点必然选择:[m][n-1],[m-1][n]
     81     int ans = max(dp[m][n - 1][m - 1][n], dp[m - 1][n][m][n-1]);
     82     //for (int i = 1; i <= m; ++i)
     83     //{
     84     //    for (int j = 1; j <= n; ++j)
     85     //    {
     86     //        for (int k = 1; k <= m; ++k)
     87     //        {
     88     //            for (int l = 1; l <= n; ++l)
     89     //            {
     90     //                //cout << "(" << i << ", " << j << ", " << k << ", " << l << ")" << " : " << dp[i][j][k][l] << endl;
     91     //                cout << dp[i][j][k][l] << "-->" << dp[k][l][i][j] << endl; 
     92     //                 /*    两条路径出发点相同,没有区分两条路径,也就是小渊和小轩怎么分配这两条路径都可以,
     93     //                    所以dp[i][j][k][l]=dp[k][l][i][j]
     94     //                 */
     95     //            }
     96     //        }
     97     //    }
     98     //}
     99     cout << ans << endl;
    100     //cout << dp[m][n - 1][m - 1][n] << " " << dp[m - 1][n][m][n - 1] << endl; // 两个值相同
    101 }
    102 
    103 int main() 
    104 {
    105     
    106 #ifdef HOME
    107     //freopen("in", "r", stdin);
    108     //freopen("out", "w", stdout);
    109     //atexit(fnExit1);
    110 #endif
    111 
    112     memset(dp, 0, sizeof(0));
    113     cin >> m >> n;
    114     for (int i = 1; i <= m; ++i)
    115     {
    116         for (int j = 1; j <= n; ++j)
    117         {
    118             cin >> arr[i][j];
    119         }
    120     }
    121     Solve();
    122 
    123 
    124 #ifdef HOME
    125     cerr << "Time elapsed: " << clock() / CLOCKS_PER_SEC << " ms" << endl;
    126     _CrtDumpMemoryLeaks();
    127     system("pause");
    128 #endif
    129     return 0;
    130 }
    
    
    
     
  • 相关阅读:
    postfix队列管理
    fdisk添加磁盘
    postfix日志分析pflogsumm
    ioctl接口内容操作
    linux 路由表设置 之 route 指令详解
    手把手教你用 Strace 诊断问题
    rtsp学习----海康RTSP客户端连接深入分析
    栈回溯技术
    objdump命令
    linux中的strip命令简介------给文件脱衣服
  • 原文地址:https://www.cnblogs.com/shijianming/p/4943978.html
Copyright © 2020-2023  润新知