AOJ 0503 - Cup

カップたちの状態をトレース(辿っていく)するだけでも時間に間に合う.
最初,出会った状態に印をつけてましたが,MLE.(じゃなくてもTLE)
そういえば,前回移動したものを戻しちゃ意味ないよなあ.これで状態に重複なくなると思いました.
そしたら,うまく行きました.(2.5sかかりましたが)
もう少し考えたら,B->Aに移動させたら,A->Bは勿論B->Aは移動できない,よってB->CかC->B.
この2つの大小関係は一意に定まる.だからできるっぽい.

辿る解法.

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

typedef long long ll;

struct Cups{
	std::vector<int> S[3];
	int t, prev_from, prev_to;
	Cups(const std::vector<int> (&_S)[3], int _t, int _from, int _to)
		:t(_t), prev_from(_from), prev_to(_to)
	{
		for(int i=0;i<3;i++){
			S[i] = _S[i];
		}
	}
};

int main(){
	int n, m;
	while(std::cin >> n >> m, n){
		std::vector<int> S[3];
		for(int i=0;i<3;i++){
			int SN;
			std::cin >> SN;
			for(int j=0;j<SN;j++){
				int e;
				std::cin >> e;
				S[i].push_back(e-1);
			}
			std::sort(S[i].begin(), S[i].end(), std::greater<int>());
		}

		std::queue<Cups> q;
		q.push(Cups(S, 0, -1, -1));
	
		int res = -1;
		while(!q.empty()){
			Cups c = q.front();q.pop();
			std::vector<int> S[3] = c.S;
			int t = c.t, prev_from = c.prev_from, prev_to = c.prev_to;

			if(t > m){
				continue;
			}
			if(S[0].size() == n || S[2].size() == n){
				res = t;
				break;
			}

			for(int i=0;i<3;i++){
				for(int j=0;j<3;j++){//i -> j
					if(std::abs(i-j) != 1 || (j == prev_from && i == prev_to) ||
						 S[i].empty() || (!S[j].empty() && S[i][0] < S[j][0]))continue;
					std::vector<int> _S[3] = S;
					_S[j].push_back(_S[i][0]);
					_S[i].erase(_S[i].begin());
					std::sort(_S[j].begin(), _S[j].end(), std::greater<int>());
					q.push(Cups(_S, t+1, i, j));
				}
			}
		}

		std::cout << res << std::endl;
	}
}

後々,色々読みました.
参考: 公式の解説(ちょーわかりやすい)
AOJ 0503: Cup - Particle(とっても簡潔.すごい.)