116
这道题是道极其明显的动归题,这道题太好玩了,我做的时候就按照一般的从左往右,而这道题要求输出的是字典序最小的,
而从右往左的话求出的就直接是字典序最小的,太神奇了
//============================================================================
// Name : 116.cpp
// Author :
// Version :
// Copyright : Your copyright notice
// Description : Hello World in C++, Ansi-style
//============================================================================
#include <iostream>
#include <cstdio>
using namespace std;
int m, n, top, ans, ansi, ansj;
int a[110][110], d[110][110], stack[110], next[110][110];
int main() {
freopen("a.txt", "r", stdin);
while(scanf("%d%d", &m, &n)!=EOF){
for(int i = 0;i < m;i++){
for(int j = 0;j < n;j++){
scanf("%d", &a[i][j]);
}
}
for(int i = 0;i < m;i++) d[i][n-1] = a[i][n-1];
for(int j = n-2;j >= 0;j--){
for(int i = 0;i < m;i++){
d[i][j] = d[i][j+1]+a[i][j];
next[i][j] = i;
if(d[i][j] >= d[(i-1+m)%m][j+1]+a[i][j]){
if(d[i][j] == d[(i-1+m)%m][j+1]+a[i][j]){
if((i-1+m)%m < next[i][j]){
next[i][j] = (i-1+m)%m;
}
}
else{
d[i][j] = d[(i-1+m)%m][j+1]+a[i][j];
next[i][j] = (i-1+m)%m;
}
}
if(d[i][j] >= d[(i+1)%m][j+1]+a[i][j]){
if(d[i][j] == d[(i+1)%m][j+1]+a[i][j]){
if((i+1)%m < next[i][j]){
next[i][j] = (i+1)%m;
}
}
else{
d[i][j] = d[(i+1)%m][j+1]+a[i][j];
next[i][j] = (i+1)%m;
}
}
}
}
ans = d[0][0];
ansi = 0;
ansj = 0;
for(int i = 1;i < m;i++){
if(ans > d[i][0]){
ans = d[i][0];
ansi = i;
ansj = 0;
}
}
printf("%d", ansi+1);
for(int i = n-2;i >= 0;i--){
ansi = next[ansi][ansj];
printf(" %d", ansi+1);
ansj++;
}
printf("\n");
printf("%d\n", ans);
}
return 0;
}

浙公网安备 33010602011771号