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; }