Stay Hungry,Stay Foolish!

E - Swap Places

E - Swap Places

https://atcoder.jp/contests/abc289/tasks/abc289_e

 

思路

T 从 1 要到 4

A 从 4 要到 1

两人同步移动

每次移动到的目标节点,花色要求不同。

设置系统i时刻所处的位置为 <Ti, Ai>

系统agent是在一个二维空间移动

初始位置 <1, n>, 目标位置为 <n, 1>

问是否路径使得初始位置可以到达目标位置; 这样就转换为图的遍历问题。

使用dfs或者bfs算法。

需要注意的是, 二维位置 是否被访问过, 也需要使用二维数据结构来存储。

 

Code -- BFS

https://atcoder.jp/contests/abc289/submissions/38948249

BFS, 使用queue遍历

遍历过程中, 为提升效率, 不能使用 dfs 的是否访问过的 visited 标记法

需要使用 inque 是否添加到队列中 标记法,

即 已经入 队列, 后续在此遇到此节点也不需要使 此节点入队列。

 
int t;
int n, m;
 
vector<int> c;
map<int, set<int> > edges;
 
typedef struct {
    int tpos;
    int apos;
    int steps;
} NODE;
 
int bfs(){
    map<int, map<int, bool> > inque;
    queue<NODE> qq;
 
    NODE node;
    
    node.tpos = 1;
    node.apos = n;
    node.steps = 0;
    
    qq.push(node);
 
    inque[1][0] = true;
 
    while(!qq.empty()){
        NODE front = qq.front();
        qq.pop();
        
        int tpos = front.tpos;
        int apos = front.apos;
        int steps = front.steps;
        
//        cout << "------ tpos = " << tpos << endl;
//        cout << "------ apos = " << apos << endl;
//        cout << "------ steps = " << steps << endl;
 
        if (tpos == n && apos == 1){
//            cout << steps << endl;
            return steps;
        }
 
        // do combination and add to queue
        for(auto tit: edges[tpos]){
            for(auto ait: edges[apos]){
                // skip if next pos colors are same
                if(c[tit] == c[ait]){
                    continue;
                }
 
                if (inque[tit][ait]){
                    continue;
                }
 
//                cout << "add one pair to queue" << endl;
//                cout << "tit = " << tit << endl;
//                cout << "ait = " << ait << endl;
 
                NODE node;
                node.tpos = tit;
                node.apos = ait;
                node.steps = steps + 1;
                
                qq.push(node);
                
                inque[tit][ait] = true;
            }
        }
    }
    
    return -1;
}
 
int main()
{
    cin >> t;
    REP(i, t){
        cin >> n >> m;
 
        c.clear();
        c.push_back(0);
        REP(j, n){
            int cj;
            cin >> cj;
            c.push_back(cj);
        }
        
        edges.clear();
        REP(j, m){
            int uj, vj;
            cin >> uj >> vj;
            
            edges[uj].insert(vj);
            edges[vj].insert(uj);
        }
        
        cout << bfs() << endl;
    }
 
    return 0;
}

 

BFS visited标记法会TLE

如下代码BFS 确使用了 visited标记法, 导致运行时间超时

具体原因如下展示, 如果使用visited标记法, 导致3被入队列两次。

 

 

https://atcoder.jp/contests/abc289/submissions/38947638

int t;
int n, m;
 
vector<int> c;
map<int, set<int> > edges;
 
typedef struct {
    int tpos;
    int apos;
    int steps;
} NODE;
 
int bfs(){
    map<int, map<int, bool> > vis;
    queue<NODE> qq;
 
    NODE node;
    
    node.tpos = 1;
    node.apos = n;
    node.steps = 0;
    
    qq.push(node);
    
    while(!qq.empty()){
        NODE front = qq.front();
        qq.pop();
        
        int tpos = front.tpos;
        int apos = front.apos;
        int steps = front.steps;
        
//        cout << "------ tpos = " << tpos << endl;
//        cout << "------ apos = " << apos << endl;
//        cout << "------ steps = " << steps << endl;
 
        vis[tpos][apos] = true;
 
        if (tpos == n && apos == 1){
//            cout << steps << endl;
            return steps;
        }
 
        // do combination and add to queue
        for(auto tit: edges[tpos]){
            for(auto ait: edges[apos]){
                // skip if next pos colors are same
                if(c[tit] == c[ait]){
                    continue;
                }
 
                if (vis[tit][ait]){
                    continue;
                }
 
//                cout << "add one pair to queue" << endl;
//                cout << "tit = " << tit << endl;
//                cout << "ait = " << ait << endl;
 
                NODE node;
                node.tpos = tit;
                node.apos = ait;
                node.steps = steps + 1;
                
                qq.push(node);
            }
        }
    }
    
    return -1;
}
 
int main()
{
    cin >> t;
    REP(i, t){
        cin >> n >> m;
 
        c.clear();
        c.push_back(0);
        REP(j, n){
            int cj;
            cin >> cj;
            c.push_back(cj);
        }
        
        edges.clear();
        REP(j, m){
            int uj, vj;
            cin >> uj >> vj;
            
            edges[uj].insert(vj);
            edges[vj].insert(uj);
        }
        
        cout << bfs() << endl;
    }
 
    return 0;
}

 

posted @ 2023-02-17 23:10  lightsong  阅读(37)  评论(0编辑  收藏  举报
Life Is Short, We Need Ship To Travel