zoukankan      html  css  js  c++  java
  • 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);
            }
        }
    }


  • 相关阅读:
    LintCode Python 简单级题目 488.快乐数
    LintCode Python 简单级题目 100.删除排序数组中的重复数字 101.删除排序数组中的重复数字II
    LintCode Python 简单级题目 373.奇偶分割数组
    LintCode Python 简单级题目 39.恢复旋转排序数组
    LintCode Python 简单级题目 35.翻转链表
    LintCode Python 简单级题目 451.两两交换链表中的节点
    LintCode Python 简单级题目 174.删除链表中倒数第n个节点
    aws查看官方centos镜像imageid
    linux shell脚本查找重复行/查找非重复行/去除重复行/重复行统计
    php配置优化-生产环境应用版
  • 原文地址:https://www.cnblogs.com/hosealeo/p/4190509.html
Copyright © 2011-2022 走看看