很大的一个错误。正向推只能保证前者最小,逆向才能保证字典序最小。附上WA的代码
#include <bits/stdc++.h>
using namespace std;
const int N = 12, M = 102;
int e[N][M], n, m;
int dp[N][M], pre[N][M];
void ptr()
{
for(int i = 1;i <= n;i ++) {
for(int j = 1;j <= m;j ++) {
printf("%3d ",dp[i][j]);
} printf("\n");
}
}
int main()
{
freopen("e:\\j1.txt","r",stdin);
freopen("e:\\j2.txt","w",stdout);
while(scanf("%d%d",&n,&m) != EOF) {
memset(dp, 0x3f, sizeof(dp));
for(int i = 1;i <= n;i ++) {
for(int j = 1;j <= m;j ++) {
scanf("%d",&e[i][j]);
}
}
for(int j = 1;j <= m;j ++) {
for(int i = 1;i <= n;i ++) {
if(j == 1) {
dp[i][j] = e[i][j];
} else {
dp[i][j] = dp[i][j - 1] + e[i][j];
pre[i][j] = i;
if(i == 1) {
if(dp[i][j] > dp[i + 1][j - 1] + e[i][j]) {
dp[i][j] = dp[i + 1][j - 1] + e[i][j];
pre[i][j] = 2;
}
if(dp[i][j] > dp[n][j - 1] + e[i][j]) {
dp[i][j] = dp[n][j - 1] + e[i][j];
pre[i][j] = n;
}
} else if(i == n) {
int ok = 0;
if(dp[i][j] >= dp[1][j - 1] + e[i][j]) {
dp[i][j] = dp[1][j - 1] + e[i][j];
pre[i][j] = 1; ok = 1;
}
if( (ok && dp[i][j] > dp[i - 1][j - 1] + e[i][j]) || (!ok && dp[i][j] >= dp[i - 1][j - 1] + e[i][j]) ) {
dp[i][j] = dp[i - 1][j - 1] + e[i][j];
pre[i][j] = n - 1;
}
} else {
if(dp[i][j] >= dp[i - 1][j - 1] + e[i][j]) {
dp[i][j] = dp[i - 1][j - 1] + e[i][j];
pre[i][j] = i - 1;
}
if(dp[i][j] > dp[i + 1][j - 1] + e[i][j]) {
dp[i][j] = dp[i + 1][j - 1] + e[i][j];
pre[i][j] = i + 1;
}
}
}
}
}
//ptr();
int now, ans = 0x3f3f3f3f;
for(int i = 1;i <= n;i ++) {
if(ans > dp[i][m]) {
ans = dp[i][m];
}
}
vector<int>p;
for(int i = 1;i <= n;i ++) {
if(dp[i][m] == ans) p.push_back(i);
}
string t;
for(int i = 0;i < p.size();i ++) {
string s;
s += p[i] + '0';
int now = p[i];
for(int k = m;k >= 2;k --) {
s += pre[now][k] + '0'; now = pre[now][k];
}
reverse(begin(s), end(s));
if(i == 0) t = s;
else t = min(t, s);
}
for(int i = 0;i < m;i ++) {
if(t[i] == ':') {
if(i == m - 1) printf("10");
else printf("10 ");
} else {
if(i == m - 1) printf("%c",t[i]);
else printf("%c ",t[i]);
}
}
printf("\n%d\n", ans);
}
return 0;
}