wioi 1043--方格取数

题目描述:

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

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

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

思路:

(1)dp,4维,dp[i1,j1,i2,j2]表示两条路分别走到(i1,j1)点和(i2,j2)点时取到的最大值

 1 #include<cstdio>
 2 #include<cstring>
 3 #include<algorithm>
 4 using namespace std;
 5
 6 int a[11][11];
 7 int dp[11][11][11][11];
 8 const int INF = 999999999;
 9
10 int operDp(int n)
11 {
12     int i1, j1, i2, j2;
13     memset(dp,0,sizeof(dp));
14     for(i1 = 1; i1 <= n; i1++)
15     for(j1 = 1; j1 <= n; j1++)
16     for(i2 = 1; i2 <= n; i2++)
17     for(j2 = 1; j2 <= n; j2++)
18     {
19         int tmp = -INF;
20         tmp = max(tmp, dp[i1-1][j1][i2-1][j2]);
21         tmp = max(tmp, dp[i1-1][j1][i2][j2-1]);
22         tmp = max(tmp, dp[i1][j1-1][i2-1][j2]);
23         tmp = max(tmp, dp[i1][j1-1][i2][j2-1]);
24         if(i1 == i2 && j1 == j2)
25             dp[i1][j1][i2][j2] = tmp + a[i1][j1];
26         else
27             dp[i1][j1][i2][j2] = tmp + a[i1][j1] + a[i2][j2];
28     }
29     return dp[n][n][n][n];
30 }
31
32 int main()
33 {
34     int n, r, c, v;
35     while(scanf("%d",&n) != EOF)
36     {
37         memset(a,0,sizeof(a));
38         while(true)
39         {
40             scanf("%d%d%d",&r,&c,&v);
41             if(!r && !c && !v) break;
42             a[r][c] = v;
43         }
44         printf("%d\n",operDp(n));
45     }
46     return 0;
47 }

(2)降低dp状态的维数

dp[k][i][j]表示走了k步,第一条路向右走了i步,第二条路向右走了j步;k最大值是向下走了n,向右走了n,也就是2*n

 1 #include<cstdio>
 2 #include<cstring>
 3 #include<algorithm>
 4 using namespace std;
 5
 6 int a[11][11];
 7 int dp[21][11][11];
 8 const int INF = 999999999;
 9
10 int operDp(int n)
11 {
12     int i, j, k;
13     memset(dp,0,sizeof(dp));
14     for(k = 1; k <= 2 * n; k++)
15     for(i = 1; i <= k; i++)
16     for(j = 1; j <= k; j++)
17     {
18         int tmp = -INF;
19         tmp = max(tmp, dp[k-1][i-1][j-1]);
20         tmp = max(tmp, dp[k-1][i-1][j]);
21         tmp = max(tmp, dp[k-1][i][j-1]);
22         tmp = max(tmp, dp[k-1][i][j]);
23         if(i == j) dp[k][i][j] = tmp + a[k-i+1][i];
24         else dp[k][i][j] = tmp + a[k-i+1][i] + a[k-j+1][j];
25     }
26     return dp[2*n][n][n];
27 }
28
29 int main()
30 {
31     int n, r, c, v;
32     while(scanf("%d",&n) != EOF)
33     {
34         memset(a,0,sizeof(a));
35         while(true)
36         {
37             scanf("%d%d%d",&r,&c,&v);
38             if(!r && !c && !v) break;
39             a[r][c] = v;
40         }
41         printf("%d\n",operDp(n));
42     }
43     return 0;
44 }

wioi 1043--方格取数,布布扣,bubuko.com

时间: 2024-10-26 03:16:19

wioi 1043--方格取数的相关文章

CodeVs 1043 方格取数

$n \times n$ 的方格,每个格子有个自然数.一人在方格中,只能向右或下走.从左上角到右下角走两次,问最大可以取得多大的数字(每个数字取了就没了,也就是说两次经过同一个位置只能得到一个值). 考虑两次一起走,每一行经过的段是两个线段假设是 [a, b] 和 [c, d].当前一行状态是 [a, b] [c, d] 时转移是来自上一行的 b 等于这一行的 a, 并且上一行的 d 等于这一行的 c. 这样的话复杂度是 $O(n^9)$,大概是不能过的,但是考虑一下剪枝,可以让 $c \ge

[CODEVS 1043] Noip 2000 方格取数

1043 方格取数 时间限制: 1s  空间限制: 128000 KB 题目描述 Description 设有N*N的方格图(N<=10,我们将其中的某些方格中填入正整数,而其他的方格中则放入数字0.如下图所示(见样例): 某人从图的左上角的A 点出发,可以向下行走,也可以向右走,直到到达右下角的B点.在走过的路上,他可以取走方格中的数(取走后的方格中将变为数字0). 此人从A点到B 点共走两次,试找出2条这样的路径,使得取得的数之和为最大. 输入描述 Input Description 输入的

tyvj 1884 [NOIP2000T4]方格取数 || codevs 1043 dp

P1884 [NOIP2000T4]方格取数 时间: 1000ms / 空间: 131072KiB / Java类名: Main 背景 [noip2000T4]方格取数 描述 设有N*N的方格图(N<=10,我们将其中的某些方格中填入正整数,而其他的方格中则放入数字0.如下图所示(见样例):某人从图的左上角的A 点出发,可以向下行走,也可以向右走,直到到达右下角的B点.在走过的路上,他可以取走方格中的数(取走后的方格中将变为数字0).此人从A点到B 点共走两次,试找出2条这样的路径,使得取得的数

hdu 1565 方格取数(2)(网络流之最大点权独立集)

题目链接:hdu 1565 方格取数(2) 题意: 有一个n*m的方格,每个方格有一个数,现在让你选一些数.使得和最大. 选的数不能有相邻的. 题解: 我们知道对于普通二分图来说,最大独立点集 + 最小点覆盖集 = 总点数,类似的,对于有权的二分图来说,有: 最大点权独立集 + 最小点权覆盖集 = 总点权和, 这个题很明显是要求 最大点权独立集 ,现在 总点权 已知,我们只要求出来 最小点权覆盖集 就好了,我们可以这样建图, 1,对矩阵中的点进行黑白着色(相邻的点颜色不同),从源点向黑色的点连一

P1004 方格取数

P1004 方格取数 题目描述 设有N*N的方格图(N<=9),我们将其中的某些方格中填入正整数,而其他的方格中则放 人数字0.如下图所示(见样例): A 0 0 0 0 0 0 0 0 0 0 13 0 0 6 0 0 0 0 0 0 7 0 0 0 0 0 0 14 0 0 0 0 0 21 0 0 0 4 0 0 0 0 15 0 0 0 0 0 0 14 0 0 0 0 0 0 0 0 0 0 0 0 0 0 . B 某人从图的左上角的A点出发,可以向下行走,也可以向右走,直到到达右下角

hdoj 1569 方格取数(2) 【最小割】 【最大点权独立集】

方格取数(2) Time Limit: 10000/5000 MS (Java/Others)    Memory Limit: 65536/32768 K (Java/Others) Total Submission(s): 5589    Accepted Submission(s): 1741 Problem Description 给你一个m*n的格子的棋盘,每个格子里面有一个非负数. 从中取出若干个数,使得任意的两个数所在的格子没有公共边,就是说所取数所在的2个格子不能相邻,并且取出的

1475: 方格取数

1475: 方格取数 Time Limit: 5 Sec  Memory Limit: 64 MBSubmit: 578  Solved: 309[Submit][Status][Discuss] Description 在一个n*n的方格里,每个格子里都有一个正整数.从中取出若干数,使得任意两个取出的数所在格子没有公共边,且取出的数的总和尽量大. Input 第一行一个数n:(n<=30) 接下来n行每行n个数描述一个方阵 Output 仅一个数,即最大和 Sample Input 2 1 2

hdu 1569 方格取数(2) 网络流 最大点权独立集

方格取数(2) Time Limit: 10000/5000 MS (Java/Others)    Memory Limit: 65536/32768 K (Java/Others) Total Submission(s): 5146    Accepted Submission(s): 1610 Problem Description 给你一个m*n的格子的棋盘,每个格子里面有一个非负数. 从中取出若干个数,使得任意的两个数所在的格子没有公共边,就是说所取数所在的2个格子不能相邻,并且取出的

HDU 1565 方格取数(1) (状态压缩 DP)

方格取数(1) Time Limit: 10000/5000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others) Total Submission(s): 5779    Accepted Submission(s): 2194 Problem Description 给你一个n*n的格子的棋盘,每个格子里面有一个非负数. 从中取出若干个数,使得任意的两个数所在的格子没有公共边,就是说所取的数所在的2个格子不能相邻,并且取出