UVA-116
题目大意:m行n列的矩阵,从第一列任意位置出发,可以往右上右下走一格,最终到达最后一列,求经过整数之和最小的路径,如果和相同则选择字典序小的路径
解体思路:dp,先顺推试着敲了下,因为要字典序存路径并比较字典序很复杂很复杂并且一直wrong
按小紫书上采用逆推简便很多
逆推代码:
#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>
#define INF 0x3f3f3f3f
using namespace std;
int m, n;
int map[100][100];
int dp[100][100];
int nx[100][100];
int main() {
while(scanf("%d%d", &m, &n) != EOF) {
for(int i = 0; i < m; i++)
for(int j = 0; j < n; j++) {
cin >> map[i][j];
}
int re = INF, x = 0;
for(int j = n-1; j >= 0; j-- ) {
for(int i = 0; i < m; i++) {
if(j == n-1)
dp[i][j] = map[i][j];
else {
int dis[3] = {i, i-1, i+1};
if(i == m-1)
dis[2] = 0;
if(i == 0)
dis[1] = m - 1;
sort(dis, dis+3);
dp[i][j] = INF;
for(int k = 0; k < 3; k++) {
int p = dp[dis[k]][j+1] + map[i][j];
if(p < dp[i][j]) {
dp[i][j] = p;
nx[i][j] = dis[k];
}
}
}
if(j == 0 && dp[i][j] < re) {
re = dp[i][j];
x = i;
}
}
}
cout << x+1;
for(int j = 0; j < n-1; j++) {
cout << ' ' << nx[x][j]+1;
x = nx[x][j];
}
cout << endl << re << endl;
}
return 0;
}
一开始正推的错误代码:
#include <iostream>
#include <cstdio>
#include <cstring>
using namespace std;
int dis[3]= {1, 0, -1};
int s[100][101];
int dp[100][101];
int m, n;
int main() {
while(scanf("%d%d", &m, &n) != EOF) {
char re[100][101];
char r[100][101];
int l = -1;
for(int i = 0; i < m; i++)
for(int j = 0; j < n; j++) {
cin >> s[i][j];
}
memset(re, 0, sizeof(re));
memset(r, 0, sizeof(r));
memset(dp, -1, sizeof(dp));
for(int i = 0; i < m; i++) {
dp[i][0] = s[i][0];
r[i][0] = i + '1';
}
for(int j = 1; j < n; j++) {
for(int i = 0; i < m; i++) {
int x, p, q;
for(int k = 0; k < 3; k++) {
p = i - dis[k];
q = j - 1;
if(p >= m)
p = p - m;
else if(p < 0)
p = p + m;
x = dp[p][q] + s[i][j];
if(dp[i][j] == -1 || x < dp[i][j] || (x == dp[i][j] && strcmp(r[p], re[i]) < 0)) {
dp[i][j] = x;
strcpy(re[i], r[p]);
}
}
re[i][j] = i + '1';
}
for(int i = 0; i < m; i++) {
strcpy(r[i], re[i]);
}
}
int g = 0;
l = dp[g][n-1];
for(int i = 1; i < m; i++) {
if(dp[i][n-1] < l || (dp[i][n-1] == l && strcmp(re[i], re[g]) < 0)) {
g = i;
l = dp[g][n-1];
}
}
for(int i = 0; i < n-1; i++) {
cout << re[g][i] << ' ';
}
cout << re[g][n-1] << endl << l << endl;
}
return 0;
}