http://acm.hdu.edu.cn/showproblem.php?pid=2571
最优化dp。状态转移方程为dp[i][j]=max{dp[i][j],dp[i-1][j]+map[i][j],dp[i][j-1]+map[i][j],dp[i][k]+map[i][j](j%k==0)};
#include <stdio.h>
#include <string.h>
#include <iostream>
#include <algorithm>
using namespace std;
const int N = 25;
const int M = 1010;
const int INF = 1e9;
int dp[N][M],num[N][M];
int main(){
// freopen("in.txt", "r", stdin);
int cas;
scanf("%d",&cas);
while(cas--){
int n,m;
scanf("%d%d",&n,&m);
for(int i=1; i<=n; i++)
for(int j=1; j<=m; j++)
scanf("%d",&num[i][j]);
for(int i=0; i<=n; i++){
for(int j=0; j<=m; j++){
dp[i][j] = -INF;
}
}
dp[1][1] = num[1][1];
for(int i=1; i<=n; i++){
for(int j=1; j<=m; j++){
dp[i][j+1] = max(dp[i][j+1], dp[i][j] + num[i][j+1]);
dp[i+1][j] = max(dp[i+1][j], dp[i][j] + num[i+1][j]);
int k = 2;
while(k * j <= m){
dp[i][k*j] = max(dp[i][k*j], dp[i][j] + num[i][k*j]);
k++;
}
}
}
// for(int i=1; i<=n; i++){
// for(int j=1; j<=m; j++){
// cout << dp[i][j] << ' ';
// }
// cout << endl;
// }
printf("%d\n",dp[n][m]);
}
return 0;
}