AOJ 0215 - Pachimon Creature

bitDPかな(違う)
あれ出力とちがうかも(違わない)
あ,通った

 C_iを属性がiのパチモンがいる場所の集合とする.
(ただし,始点,終点をそれぞれ C_S, C_Gとしパチモンと見る.)
お供のパチモンの属性を選ぶ( C_0とする)
 C_1 C_0を捕まえられる属性, C_2 C_1を...とする.
 C_S, C_1, C_2, C_3, C_4, C_Gの最短路を求める.
このとき,メモ化を用いるといいです.
C_0の選び方は5通り,全てに対して調べ最小の値を得る.
頑張って図にしてみました.

#include<iostream>
#include<vector>
#include<algorithm>

struct P{
    int x, y;
};
 
std::vector<P> creature[7];//0は始点, 6は終点となっている
const int INF = 1 << 24;
//dp[ゲットしたパチモンの匹数][さっきつかまえた種族][さっきつかまえたパチモンの番号]: 最小手数
int dp[5][5][1000];
 
int rec(int i, int t, int n){
	if(dp[i][t][n] >= 0){
		return dp[i][t][n];
	}
 
	if(i == 4){
		int x_diff = abs(creature[6][0].x - creature[t][n].x),
			y_diff = abs(creature[6][0].y - creature[t][n].y);
		return x_diff + y_diff;
	}

	//t+1へ行こう
	int res = INF, prev_res;
	for(int v=0;v<creature[t+1].size();v++){
		int x_diff = abs(creature[t+1][v].x - creature[t][n].x),
			y_diff = abs(creature[t+1][v].y - creature[t][n].y);
		res = std::min(res, rec(i+1, t+1, v) + x_diff + y_diff);
	}

	return dp[i][t][n] = res;
}
 
int main(){
	int w, h;
	while(std::cin >> w >> h, w){
		for(int i=0;i<7;i++)creature[i].clear();
 
		for(int i=0;i<h;i++){
			for(int j=0;j<w;j++){
				char c;
				std::cin >> c;
				if(c == 'S'){
					creature[0].push_back({j, i});
				}else if(c == 'G'){
					creature[6].push_back({j, i});
				}else if('1' <= c && c <= '5'){
					creature[c-'0'].push_back({j, i});
				}
			}
		}
 
		int res = INF, type;
		for(int i=1;i<=5;i++){
			for(int S=0;S<5;S++){
				for(int t=0;t<5;t++){
					for(int n=0;n<1000;n++){
						dp[S][t][n] = -1;
					}
				}
			}

			std::rotate(creature+1, creature+2, creature+6);

			if(rec(0, 0, 0) < res){
				res = rec(0, 0, 0);
				type = i;
			}
		}
 
		if(res == INF){
			std::cout << "NA" << std::endl;
		}else{
			std::cout << type << " " << res << std::endl;
		}
	}
}