TLE求助!
查看原帖
TLE求助!
244309
yuhaocheng楼主2021/10/30 22:07

代码:

#include <bits/stdc++.h>
using namespace std;

typedef long long ll;

const int maxw = 20;

const int dx[5] = {0, 0, 0,-1, 1};
const int dy[5] = {0,-1, 1, 0, 0};

int w, h, n;
char a[maxw][maxw];

int targx[3];
int targy[3];

struct State { //一个状态 
    int x[3] = {}, y[3] = {}; //3只鬼的位置 
    int d; //已经走了d步 
    void operator=(State st) { //复制状态 
        x[0] = st.x[0];
        x[1] = st.x[1];
        x[2] = st.x[2];
        y[0] = st.y[0];
        y[1] = st.y[1];
        y[2] = st.y[2];
        d = st.d;
    }
};

set<ll> vis;

int state2num(State st) { //把一个状态转换成一个数 
	int ret = 0;
	for(int i = 0; i < n; i++) {
		ret = (ret << 4) + st.x[i] - 1;
	}
	for(int i = 0; i < n; i++) {
		ret = (ret << 4) + st.y[i] - 1;
	}
	return ret;
} 

void init() {
	vis.clear(); //清空访问标记 
}

void input(queue<State> &q) {
	init();
    int cnt = 0;
    int ch2num[130];
    memset(ch2num, -1, sizeof(ch2num));
    State start;
    for(int i = 1; i <= h; i++) {
        fgets(a[i] + 1, 20, stdin);
        for(int j = 1; j <= w; j++) {
            char lowch = tolower(a[i][j]);
            if(a[i][j] >= 'a' && a[i][j] <= 'z') { //遇到一只鬼 
                if(ch2num[lowch] != -1) { //未标记这只鬼 
                    start.x[ch2num[lowch]] = i;
                    start.y[ch2num[lowch]] = j; //记录初始位置 
                } else {
                    ch2num[lowch] = cnt; //新增编号 
                    start.x[cnt] = i;
                    start.y[cnt] = j; //记录初始位置 
                    cnt++; //当前编号被用了,可用编号加1
                }
            } else if(a[i][j] >= 'A' && a[i][j] <= 'Z') { //遇到一只鬼的目标位置 
                if(ch2num[lowch] != -1) { //未标记这只鬼 
                    targx[ch2num[lowch]] = i;
                    targy[ch2num[lowch]] = j; //记录目标位置 
                } else {
                    ch2num[lowch] = cnt; //新增编号 
                    targx[cnt] = i;
                    targy[cnt] = j; //记录目标位置 
                    cnt++; //当前编号被用了,可用编号加1
                }
            }
        }
        //getchar();
    }
    /*
    for(int i = 0; i < n; i++) {
        printf("targ %d: (%d, %d)\n", i, targx[i], targy[i]);
    }
    for(int i = 0; i < n; i++) {
        printf("now %d: (%d, %d)\n", i, start.x[i], start.y[i]);
    }
    */
    start.d = 0;
    vis.insert(state2num(start));
    q.push(start);
}

bool check(State st) { //检查st是否是目标状态 
    for(int i = 0; i < n; i++) {
        if(st.x[i] != targx[i] || st.y[i] != targy[i]) { //与目标状态不符 
            return false; //不是 
        }
    }
    return true; //是 
}

void solve() {
    //init
    queue<State> q;
    input(q); //输入+压入初始状态 
    //bfs
    while(!q.empty()) {
        State u = q.front(); //取队首状态 
        q.pop();
        if(check(u)) { //到达目标状态 
            printf("%d\n", u.d);
            return;
        }
        for(int i = 0; i < 5; i++) { //遍历每一个鬼的移动方向 
            for(int j = 0; j < 5; j++) {
                for(int k = 0; k < 5; k++) {
                	if(i == 0 && j == 0 && k == 0) { //全都原地不动 
                		continue;
					}
                    State tmp = u;
                    tmp.x[0] += dx[i];
                    tmp.y[0] += dy[i];
                    tmp.x[1] += dx[j];
                    tmp.y[1] += dy[j];
                    tmp.x[2] += dx[k];
                    tmp.y[2] += dy[k]; //移动 
                    tmp.d++; //步数加1 
                    bool flag = false;
                    for(int i = 0; i < n; i++) {
                    	if(a[tmp.x[i]][tmp.y[i]] == '#') { //遇到障碍物 
//                    		printf("0\n");
//							printf("u: (%d, %d)\ntmp: (%d, %d)\nd: %d\n", u.x[i], u.y[i], tmp.x[i], tmp.y[i], tmp.d);
                    		flag = true;
                    		break;
//							continue;
						}
						for(int j = i + 1; j < n; j++) {
							if((tmp.x[i] == tmp.x[j] && tmp.y[i] == tmp.y[j]) || (tmp.x[i] == u.x[j] && tmp.y[i] == u.y[j] && tmp.x[j] == u.x[i] && tmp.y[j] == u.y[i])) { //两个鬼在同一位置或交换了位置 
								flag = true;
								break;
							}
						}
						if(flag) {
							break;
//							continue;
						}
					}
					if(flag) { //非法移动 
						continue;
					}
					
//					bool flag = false;
//                    for(int i = 0; i < n; i++) {
//                    	if(a[tmp.x[i]][tmp.y[i]] == '#') {
////                    		printf("0\n");
////                    		flag = true;
////                    		break;
//							continue;
//						}
//					}
//					if(flag) {
////						continue;
//					}
					int num = state2num(tmp);
                    if(!vis.count(num)) { //没有访问过这个状态 
                    	vis.insert(num); //标记访问 
                        q.push(tmp); //入队 
                    }
                }
            }
        }
    }
    cout << "Error!" << endl;
}

int main() {
//	freopen("..\\in.txt", "r", stdin);
//	freopen("..\\out.txt", "w", stdout);
    while(cin >> w >> h >> n && w != 0) { //输入 
		getchar();
        solve();
    }
}
2021/10/30 22:07
加载中...