hbrust 1593圈套(动态规划)
动态规划的关键就是找到状态转移方程。本题的当前状态有三种情况,map[i-1][j], map[i][j-1], 以及行上能被改行整除的,判断一下就行。
写的有点复杂了,还可以再优化的。
圈套 | ||||||
|
||||||
Description | ||||||
Wd在回答了使者的问题之后,使者告诉他只要将原来对应数字用得到的数字替换掉即可,wd试了之后发现六芒星图案消失了,但是随之出现的是一个方格阵,而wd和Cc位于方格阵的左上角,而使者位于方格阵的右下角,wd发现已经中了使者的圈套。每个方格中会有若干的数字,数字有正有负,如果经过那个方格的数字是非负整数,wd就可以立刻恢复相应数量的体力,而方格的数字如果是负数,那么就会立刻减少相应数量的体力。Cc发现每次只能向下或者向右走,如果向下走只能走一格,而如果向右走,每次可以走一格或者走到该行的列数是当前所在列数倍数的格子。例如:wd所在位置是(x, y),那么他只能移动到 (x+1,y) 或者 (x,y+1) 或者(x,k*y)(k>1) 的位置的格子,当然他不能走到格子外。wd想知道和使者交战时最多还有多少的体力(假设方格阵出现之前体力为0)。 |
||||||
Input | ||||||
多组测试数据,第一行一个整数T表示数据的总数, 每组测试数据第一行为两个整数n,m分别表示行数和列数(1<=n<=20,10<=m<=1000); 接着是n行数据,每行包含m个整数,表示n行m列的格子对应的数字k( |k|<100 )。 |
||||||
Output | ||||||
对于每组数据,输出一个整数表示到达最后一格后的wd最大体力值。 |
||||||
Sample Input | ||||||
1 3 8 9 10 10 10 10 -10 10 10 10 -11 -1 0 2 11 10 -20 -11 -11 10 11 2 10 -10 -10 |
||||||
Sample Output | ||||||
52 |
||||||
Hint | ||||||
体力值可以为负数,左上角(wd起始位置),右下角(使者所在位置)上的数值也要计算在内
1 #include<stdio.h> 2 #include<string.h> 3 4 int map[25][1001]; 5 6 int main(void) 7 { 8 int t; 9 int n, m; 10 11 scanf("%d", &t); 12 13 while (t--) 14 { 15 scanf("%d%d", &n, &m); 16 17 for (int i=1; i<=n; i++) 18 { 19 for (int j=1; j<=m; j++) 20 { 21 scanf("%d", &map[i][j]); 22 } 23 } 24 25 for (int i=2; i<=m; i++) //特 26 { 27 int q = map[1][i-1] + map[1][i]; 28 int t = -101; // 殊 29 for (int j=1; j<i; j++) 30 { //位 31 if (i%j==0 && map[1][j]+map[1][i] > t) 32 { 33 t = map[1][j] + map[1][i]; //置 34 } 35 } 36 map[1][i] = t > q ? t : q; 37 } //处 38 for (int i=2; i<=n; i++) 39 { 40 map[i][1] += map[i-1][1]; 41 } //理 42 43 for (int i=2; i<=n; i++) 44 { 45 for (int j=2; j<=m; j++) 46 { 47 int w = map[i][j-1] + map[i][j];//由行的来的 48 int q = map[i-1][j] + map[i][j];//由前一个列得来的 49 int t = -101; 50 for (int k=1; k<j; k++) //状态 51 { 52 if (j%k==0 && map[i][k] + map[i][j] > t) 53 { 54 t = map[i][k] + map[i][j]; 55 } 56 } 57 if (q > t) 58 { 59 t = q; 60 } 61 map[i][j] = t > w ? t : w; 62 } 63 } 64 printf("%d\n", map[n][m]); 65 } 66 return 0; 67 }
|