2015合肥网络赛 HDU 5492 Find a path 动归
题意:给你一个矩阵求一个路径使得 最小。
思路:
方法一:数据特别小,直接枚举权值和(n + m - 1) * aver,更新答案。
方法二:用f[i][j][k]表示到达[i,j]是权值和为k时平方和的最大值,转移方程就是
f[i][j][k] = min(f[i][j][k], min(f[i - 1][j][k - a[i][j]] + sqr(a[i][j]), f[i][j - 1][k - a[i][j]] + sqr(a[i][j])));
1 #include <iostream> 2 #include <cstdio> 3 #include <fstream> 4 #include <algorithm> 5 #include <cmath> 6 #include <deque> 7 #include <vector> 8 #include <queue> 9 #include <string> 10 #include <cstring> 11 #include <map> 12 #include <stack> 13 #include <set> 14 #define eps 1e-8 15 #define INF 0x3f3f3f3f 16 #define LL long long 17 #define MAXN 10005 18 #define sqr(x) (x) * (x) 19 using namespace std; 20 int n, m, s; 21 int a[35][35], f[35][35]; 22 int find(int x){ 23 //s(n + m - 1)* sigma(sqr((a[i] - aver))) 24 memset(f, 0, sizeof(f)); 25 for (int i = 1; i <= n; i++){ 26 for (int j = 1; j <= m; j++){ 27 if (i == 1 && j == 1){ 28 f[1][1] = sqr(s * a[1][1] - x); 29 continue; 30 } 31 if (i == 1){ 32 f[i][j] = f[i][j - 1] + sqr(s * a[i][j] - x); 33 continue; 34 } 35 if (j == 1){ 36 f[i][j] = f[i - 1][j] + sqr(s * a[i][j] - x); 37 continue; 38 } 39 f[i][j] = min(f[i - 1][j] + sqr(s * a[i][j] - x), f[i][j - 1] + sqr(s * a[i][j] - x)); 40 } 41 } 42 return f[n][m] / s; 43 } 44 int main() 45 { 46 #ifndef ONLINE_JUDGE 47 freopen("in.txt", "r", stdin); 48 //freopen("out.txt", "w", stdout); 49 #endif // OPEN_FILE 50 int T; 51 scanf("%d", &T); 52 int cas = 1; 53 while (T--){ 54 scanf("%d%d", &n, &m); 55 s = n + m - 1; 56 for (int i = 1; i <= n; i++){ 57 for (int j = 1; j <= m; j++){ 58 scanf("%d", &a[i][j]); 59 } 60 } 61 int ans = INF; 62 for (int i = 1; i <= 1805; i++){ 63 ans = min(ans, find(i)); 64 } 65 printf("Case #%d: %d\n", cas++, ans); 66 } 67 }
1 #include <iostream> 2 #include <cstdio> 3 #include <fstream> 4 #include <algorithm> 5 #include <cmath> 6 #include <deque> 7 #include <vector> 8 #include <queue> 9 #include <string> 10 #include <cstring> 11 #include <map> 12 #include <stack> 13 #include <set> 14 #define eps 1e-8 15 #define INF 0x3f3f3f3f 16 #define LL long long 17 #define MAXN 10005 18 #define sqr(x) (x) * (x) 19 using namespace std; 20 int n, m, s; 21 int a[35][35], f[35][35][1805]; 22 23 int main() 24 { 25 #ifndef ONLINE_JUDGE 26 freopen("in.txt", "r", stdin); 27 //freopen("out.txt", "w", stdout); 28 #endif // OPEN_FILE 29 int T; 30 scanf("%d", &T); 31 int cas = 1; 32 while (T--){ 33 scanf("%d%d", &n, &m); 34 s = n + m - 1; 35 for (int i = 1; i <= n; i++){ 36 for (int j = 1; j <= m; j++){ 37 scanf("%d", &a[i][j]); 38 } 39 } 40 memset(f, INF, sizeof(f)); 41 for (int i = 1; i <= n; i++){ 42 for (int j = 1; j <= m; j++){ 43 for (int k = 0; k <= 1805; k++){ 44 if (i == 1 && j == 1){ 45 f[i][j][a[1][1]] = sqr(a[1][1]); 46 continue; 47 } 48 if (k < a[i][j]) continue; 49 if (i == 1){ 50 f[i][j][k] = min(f[i][j - 1][k - a[i][j]] + sqr(a[i][j]), f[i][j][k]); 51 continue; 52 } 53 if (j == 1){ 54 f[i][j][k] = min(f[i - 1][j][k - a[i][j]] + sqr(a[i][j]), f[i][j][k]); 55 continue; 56 } 57 f[i][j][k] = min(f[i][j][k], 58 min(f[i - 1][j][k - a[i][j]] + sqr(a[i][j]), f[i][j - 1][k - a[i][j]] + sqr(a[i][j]))); 59 60 } 61 } 62 } 63 int ans = INF; 64 int s = n + m - 1; 65 for (int i = 0; i <= 1801; i++){ 66 if (f[n][m][i] == INF) continue; 67 ans = min(ans, s * f[n][m][i] - sqr(i)); 68 } 69 printf("Case #%d: %d\n", cas++, ans); 70 } 71 }