• 2014百度之星初赛第一轮解题报告:information


    Information
    时间限制: 1s 内存限制: 65536K
    问题描述
    军情紧急,我们需要立刻开发出一个程序去处理前线侦察兵发回的情报,并做出相应的分析。现在由你负责其中的一个子模块,你需要根据情报计算出敌方坦克的位置。
    当敌方坦克静止时,侦察兵会尽力估算出它们之间的位置,而每当敌方坦克移动时,侦察兵都会记录下坦克新的位置并向你报告。每个坦克的位置可以由一个二维整数坐标来描述。
    前线发回的情报有四种格式:
    1 A B X Y
    表示A坦克移动到了与B坦克的相对位置是                              的地方,即 
    2 A X Y
    表示A坦克移动到了绝对位置是 的地方,即 , 
    3 A B X Y
    表示发现了A坦克与B坦克的相对位置是 ,即 
    4 A X Y
    表示发现了A坦克的绝对位置是 ,即 , 
    我们需要你对于如下两种询问及时做出回应:
    5 A B
    表示询问A坦克与B坦克的相对位置是多少,即分别求出 以及 
    6 A
    表示询问A坦克的绝对位置是多少,即求出 
    其中AB代表的是任意的一个坦克的编号,(X,Y)表示了坦克的二维坐标。你可以假设初始时刻我们对于敌方任何坦克的位置都一无所知,在此之后坦克的每一次移动都被侦察兵侦察到了。请注意两个坦克的坐标有可能相同。
    输入
    输入的第一行是一个整数TT< 1000),表示共有T组数据。
    对于每组数据,第一行有一个整数N,表示这组数据有N次查询。接下来的每行表示一次查询,每次查询第一个数字代表是哪种询问,询问的格式详见上文。
    数据范围:
    XY都是整数且
    测试数据中98%的数据N不超过50
    输出
    对于每组数据,首先需要输出单独一行”Case#?:”,其中问号处应填入当前的数据组数,组数从1开始计算。
    对于每一个类型(1)或者(2)的询问,请把它们加入到你的记录中。
    对于每一个类型(3)或者(4)的询问,如果与之前记录的内容有矛盾,请输出”REJECT”并将这个情报忽略掉,如没有矛盾,请把它们加入到你的记录中。
    对于每一个类型(5)或者(6)的询问,如果根据之前的记录能推出结论,请输出两个整数XY,两个整数之间有一个空格;如果不能推出结论,请输出”UNKNOWN”。输出的所有信息都不包括引号。
    样例输入
    2
    7
    1 1 2 3 4
    2 3 4 5
    3 4 5 2 1
    4 6 2 2
    3 2 4 6 2
    5 4 1
    6 3
    6
    6 3
    4 3 2 2
    6 3
    2 4 2 3
    5 3 4
    3 3 4 1 2
    样例输出
    Case #1:
    -9 -6
    4 5
    Case #2:
    UNKNOWN
    2 2
    0 -1
    REJECT


    解题报告 –Information
    这题的算法并不复杂,主要就是一个并查集的使用,不过写的时候要注意很多细节。每个Tank的状态可以分3种情况:
    1.      未初始化,不在任何集合里;
    2.      在一个互相间已知相对位置的集合里;
    3.      已知绝对位置。
    具体的处理规则如下:
    1.      1A B X Y
    1)        如果A原来在一个集合里,把它从这个集合移除;
    2)        根据B的情况:
    a)        如果B已知绝对位置,设置A的绝对位置;
    b)        如果B不在任何集合里,则创建一个集合,把A、B都加入,并设置相对位置;
    c)        如果B已经在一个集合里,则把A加入这个集合,并设置相对位置;
    2.  2 A X Y
    1)        如果A原来在一个集合里,把它从这个集合移除;
    2)   设置A的绝对位置;
    3.  3 A B XY
    1)   如果A和B其中一个不在任何集合里,则等于把其移到另一个的相对位置上,和类型1的处理流程一样;
    2)   如果A和B都有绝对位置或者在同一个集合里,判断他们的相对位置是否和这次发现的一致,如果不一致,输出REJECT,忽略本次操作;
    3)   如果A和B其中一个有绝对位置,则可以把另外一个所在集合里的所有Tank都设置绝对位置;
    4)   如果A和B在不同的集合里,则把其中一个集合合并到另一个集合,并更新所有Tank的相对位置;
    4.  4 A X Y
    1)   如果A已经有绝对位置,判断他的绝对位置是否和这次发现的一致,如果不一致,输出REJECT,忽略本次操作;
    2)   如果A不在任何集合内,设置A的绝对位置即可;
    3)   如果A在一个集合内,设置这个集合里的所有Tank的绝对位置;
    5.  5 A B
    1)   如果A和B都有绝对位置或者在同一个集合里,输出他们的相对位置;
    2)   否则输出UNKNOWN;
    6.  6 A
    1)   如果A有绝对位置,输出A的绝对位置;
    2)   否则输出UNKNOWN。

    解题代码:

    #include <set>
    #include <string>
    #include <stdio.h>
    using namespace std;
    
    struct Tank {
        int id;
        int x;
        int y;
    };
    
    Tank tank[100005];
    int id;
    set<int> tanks[100005];
    FILE* fout = NULL;
    
    void insert(int m, int a, int b, int x, int y) {
        if (m == 1) {
            if (tank[b].id == -2) {
                tank[b].id = id++;
                tank[b].x = tank[b].y = 0;
                tanks[tank[b].id].insert(b);
            }
            if (tank[a].id >= 0) {
                tanks[tank[a].id].erase(a);
            }
            tank[a].id = tank[b].id;
            if (tank[a].id >= 0) {
                tanks[tank[a].id].insert(a);
            }
            tank[a].x = tank[b].x + x;
            tank[a].y = tank[b].y + y;
        }
        else if (m == 2) {
            if (tank[a].id >= 0) {
                tanks[tank[a].id].erase(a);
            }
            tank[a].id = -1;
            tank[a].x = x;
            tank[a].y = y;
        }
        else if (m == 3) {
            if (tank[a].id == -2) {
                insert(1, a, b, x, y);
            }
            else if (tank[b].id == -2) {
                insert(1, b, a, -x, -y);
            }
            else if (tank[a].id == -1 && tank[b].id == -1) {
                if (tank[a].x != tank[b].x + x || tank[a].y != tank[b].y + y) {
                    fprintf(fout, "REJECT
    ");
                }
            }
            else if (tank[a].id == -1) {
                insert(4, b, -1, tank[a].x - x, tank[a].y - y);
            }
            else if (tank[b].id == -1) {
                insert(4, a, -1, tank[b].x + x, tank[b].y + y);
            }
            else {
                if (tank[a].id == tank[b].id) {
                    if (tank[a].x != tank[b].x + x || tank[a].y != tank[b].y + y) {
                        fprintf(fout, "REJECT
    ");
                    }
                }
                else {
                    int dx = tank[b].x + x - tank[a].x;
                    int dy = tank[b].y + y - tank[a].y;
                    int j = tank[a].id;
                    int k = tank[b].id;
                    for (set<int>::const_iterator itr = tanks[j].begin(); itr != tanks[j].end(); itr++) {
                        tank[*itr].id = tank[b].id;
                        tank[*itr].x += dx;
                        tank[*itr].y += dy;
                        tanks[k].insert(*itr);
                    }
                    set<int> temp;
                    tanks[j].swap(temp);
                }
            }
        }
        else if (m == 4) {
            if (tank[a].id == -1) {
                if (tank[a].x != x || tank[a].y != y) {
                    fprintf(fout, "REJECT
    ");
                }
            }
            else if (tank[a].id == -2) {
                tank[a].id = -1;
                tank[a].x = x;
                tank[a].y = y;
            }
            else {
                int dx = x - tank[a].x;
                int dy = y - tank[a].y;
                int j = tank[a].id;
                for (set<int>::const_iterator itr = tanks[j].begin(); itr != tanks[j].end(); itr++) {
                    tank[*itr].id = -1;
                    tank[*itr].x += dx;
                    tank[*itr].y += dy;
                }
                set<int> temp;
                tanks[j].swap(temp);
            }
        }
    }
    
    void query(int m, int a, int b) {
        if (m == 5) {
            if (tank[a].id > -2 && tank[b].id > -2 && tank[a].id == tank[b].id) {
                fprintf(fout, "%d %d
    ", tank[a].x - tank[b].x, tank[a].y - tank[b].y);
            }
            else {
                fprintf(fout, "UNKNOWN
    ", m, a, b);
            }
        }
        else {
            if (tank[a].id == -1) {
                fprintf(fout, "%d %d
    ", tank[a].x, tank[a].y);
            }
            else {
                fprintf(fout, "UNKNOWN
    ", m, a);
            }
        }
    }
    
    int main() {
        int T, N, t = 1;
        int m = 0, a = 0, b = 0, x = 0, y = 0;
        FILE* fp = stdin; //fopen("data.in", "r");
        fout = stdout; //fopen("output", "w");
    
        fscanf(fp, "%d", &T);
        while (T--) {
            fscanf(fp, "%d", &N);
            for (int i = 0; i <= N; i++) {
                tank[i].id = -2;
            }
            id = 0;
            fprintf(fout, "Case #%d:
    ", t++);
    
            while (N--) {
                fscanf(fp, "%d", &m);
                if (m == 1 || m == 3) {
                    fscanf(fp, "%d %d %d %d", &a, &b, &x, &y);
                    insert(m, a, b, x, y);
                }
                else if (m == 2 || m == 4) {
                    fscanf(fp, "%d %d %d", &a, &x, &y);
                    insert(m, a, b, x, y);
                }
                else if (m == 5) {
                    fscanf(fp, "%d %d", &a, &b);
                    query(m, a, b);
                }
                else if (m == 6) {
                    fscanf(fp, "%d", &a);
                    query(m, a, b);
                }
            }
    
            for (int i = 0; i < id; i++) {
                set<int> temp;
                tanks[i].swap(temp);
            }
        }
    }


  • 相关阅读:
    windows7环境下使用pip安装MySQLdb
    ZeroMQ
    LazyValue<T>
    方法执行失败,重复执行指定次数某个方法
    关于截取字符串substr和substring两者的区别
    C#的字符串优化-String.Intern、IsInterned
    几张图轻松理解String.intern()
    string 线程安全
    请问C#中string是值传递还是引用传递?
    C# String与StringBuilder
  • 原文地址:https://www.cnblogs.com/hosealeo/p/4190509.html
Copyright © 2020-2023  润新知