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

posted @ 2011-06-09 12:02  KOKO's  阅读(216)  评论(0编辑  收藏  举报