hbrust 1593圈套(动态规划)

动态规划的关键就是找到状态转移方程。本题的当前状态有三种情况,map[i-1][j], map[i][j-1], 以及行上能被改行整除的,判断一下就行。

写的有点复杂了,还可以再优化的。

 

                                                                                                                              圈套
Time Limit: 1000 MS Memory Limit: 32768 K
Total Submit: 5(4 users) Total Accepted: 5(4 users) Rating:  Special Judge: No
Description

    Wd在回答了使者的问题之后,使者告诉他只要将原来对应数字用得到的数字替换掉即可,wd试了之后发现六芒星图案消失了,但是随之出现的是一个方格阵,而wdCc位于方格阵的左上角,而使者位于方格阵的右下角,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个整数,表示nm列的格子对应的数字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 }

 

posted @ 2012-12-07 12:11  尔滨之夏  阅读(307)  评论(0编辑  收藏  举报