zoukankan      html  css  js  c++  java
  • POI2001 Ants and the ladybug ***

    直接模拟, 刚开始把题意理解错了,以为每次只有一只蚂蚁走,其实正确的是蚂蚁一哄而上,然后按照题意,各只蚂蚁分别在该停的位置停下。

      

      

     先转一个吧: http://www.byvoid.com/blog/poi-2001-mro/

      

      

      

      

    做出这道题关键在于读懂题目,尤其是第3条和第4条规则。可以知道,所有蚂蚁是一拥而上的,而且蚂蚁很聪明,它们知道如果在某时一只蚂蚁到瓢虫的路 径与另一只蚂蚁的路径相互包含,就让距离近的蚂蚁继续行进,另一只蚂蚁停留不动。蚂蚁们还会互相礼让,如果要同时进入一个节点,就让编号小的蚂蚁进入,其 它蚂蚁停止不再动。

    瓢虫会停留在多个位置,但是都是互相不关联的,我们可以把瓢虫停留的每个位置看作独立的测试点,每个测试点要用到上个测试点的结果,所以我们可以分割考虑每次瓢虫停留。

    对于每次瓢虫停留,如果简单地模拟,会很容易超时。我们要把每只蚂蚁一次移动到位。首先从瓢虫的位置开始一遍BFS,找到所有可行进的蚂 蚁,记录每只蚂蚁到瓢虫位置的路径。然后按照路径长度从小到大为第一关键字,蚂蚁编号从小到大为第二关键字把蚂蚁进行排序,排名第一的蚂蚁一定是可以驱逐 瓢虫的蚂蚁,把它的路径上的顶点分别标记时间。然后依次处理每只蚂蚁,如果某只蚂蚁路径上有节点已经被标记时间,则这只蚂蚁的最大移动时间就是已经标记的 时间。在移动时也标记时间,用于影响后面的蚂蚁。这样,移动所有蚂蚁的时间复杂度是O(N+K)的。

    算法的总的时间复杂度为O((N+K*logK)*L),可以很快解决问题。实际编写时有很多细节需要注意。

        

        

        

    /* 
    * Problem: POI2001 mro
    * Author: Guo Jiabao
    * Time: 2009.2.2 21:43
    * State: Solved
    */
    #include <iostream>
    #include <cstdio>
    #include <cstdlib>
    #include <cmath>
    #include <cstring>

    using namespace std;

    const int MAXN=5001,MAXK=1001,INF=0x7FFFFFFF;

    struct edge{int t;edge *next;};
    struct adjl{edge *f,*l;};
    struct vertex{int id,ant,label;};
    struct ant{int vtx,id,dist,hits;};
    struct path{path *from;int p;};

    edge E[MAXN*2];
    adjl A[MAXN];
    vertex V[MAXN];
    ant Ant[MAXK];
    int PL[MAXK],Pt[MAXK][MAXN];
    int N,K,L,Ec=-1,Target;
    int Order[MAXK];

    inline void addedge(int a,int b)
    {
    if (A[a].f)
    A[a].l=A[a].l->next=&E[++Ec];
    else
    A[a].f=A[a].l=&E[++Ec];
    E[Ec].t=b;
    }

    void init()
    {
    int i,a,b;
    freopen("mro.in","r",stdin);
    freopen("mro.out","w",stdout);
    scanf("%d",&N);
    for (i=1;i<N;i++)
    {
    scanf("%d%d",&a,&b);
    addedge(a,b);
    addedge(b,a);
    }
    for (i=1;i<=N;i++)
    V[i].id=i;
    scanf("%d",&K);
    for (i=1;i<=K;i++)
    {
    scanf("%d",&a);
    V[a].ant=i;
    Ant[i].id=i;
    Ant[i].vtx=a;
    Order[i]=i;
    }
    scanf("%d",&L);
    }

    void BFS()
    {
    path Queue[MAXN],u,v;
    int Head=0,Tail=0;
    bool vis[MAXN];
    int *P;
    memset(vis,0,sizeof(vis));
    Queue[0].p=Target;
    Queue[0].from=0;
    vis[Target]=true;
    while (Head<=Tail)
    {
    v.from=&Queue[Head];
    u=Queue[Head++];
    for (edge *k=A[u.p].f;k;k=k->next)
    {
    v.p=k->t;
    if (!vis[v.p])
    {
    vis[v.p]=true;
    if (V[v.p].ant!=0)
    {
    int a=V[v.p].ant;
    path *b=&v;
    PL[a]=0;
    P=Pt[a];
    while (b->from)
    {
    P[++PL[a]]=b->p;
    b=b->from;
    }
    P[++PL[a]]=Target;
    Ant[a].dist=PL[a]-1;
    }
    else
    Queue[++Tail]=v;
    }
    }
    }
    }

    void Move()
    {
    int p,i,j,u,v,MaxStep,Step;
    i=Order[1];
    Ant[i].hits++;
    MaxStep=PL[i];
    for (p=1;p<=K && Ant[i=Order[p]].dist<INF;p++)
    {
    Step=MaxStep;
    for (j=1;j<=PL[i];j++)
    {
    u=Pt[i][j];
    if (V[u].label)
    {
    Step=V[u].label+1;
    break;
    }
    }
    u=Pt[i][1];
    V[u].ant=0;
    for (j=2;j<=Step;j++)
    {
    v=Pt[i][j];
    if (V[u].label+1 > V[v].label)
    V[v].label=V[u].label+1;
    else
    break;
    u=v;
    }
    Ant[i].vtx=u;
    V[u].ant=i;
    }
    }

    inline int cmp(const void *a,const void *b)
    {
    int A=*(int *)a,B=*(int *)b;
    if ( Ant[A].dist < Ant[B].dist ) return -1;
    if ( Ant[A].dist > Ant[B].dist ) return 1;
    if ( Ant[A].id < Ant[B].id ) return -1;
    return 1;
    }

    void clear()
    {
    int i;
    for (i=1;i<=K;i++)
    Ant[i].dist=INF;
    for (i=1;i<=N;i++)
    V[i].label=0;
    }

    void solve()
    {
    int i,a;
    for (i=1;i<=L;i++)
    {
    scanf("%d",&Target);
    if (V[Target].ant!=0)
    {
    a=V[Target].ant;
    Ant[a].hits++;
    }
    else
    {
    clear();
    BFS();
    qsort(Order+1,K,sizeof(Order[0]),cmp);
    Move();
    }
    }
    for (i=1;i<=K;i++)
    {
    printf("%d %dn",Ant[i].vtx,Ant[i].hits);
    }
    }

    int main()
    {
    init();
    solve();
    return 0;
    }

      

      

      

        

      

      

    ------------------------------------------------------------------------------------------------------------------------

      

        

      

        

     下面是自己写的错误理解的代码,也贴上来吧:

      

      

      

        

    /*
    * Ants and the ladybug .cpp
    *
    * Created on: 2011-10-6
    *
    */
    #include <cstdio>
    #include <cstring>
    using namespace std;

    const int maxN = 5000 + 5;
    const int maxK = 1000 + 5;
    const int maxL = 500 + 5;

    int n, k, l, antPos[maxK], chaseTime[maxK] = {};
    int queue[maxN], head, tail;
    bool vis[maxN] = {};

    struct SList{
    int to;
    SList *next;

    SList(): next(NULL) {}
    };
    struct STree{
    int antNum;
    SList list;

    STree(): antNum(-1) {}
    };

    STree tree[maxN];


    void cal(int bugPos){
    //bug所在位置就有蚂蚁
    if(tree[bugPos].antNum != -1){
    antPos[tree[bugPos].antNum] = bugPos;
    chaseTime[tree[bugPos].antNum]++;
    return;
    }

    SList *tmpList = &tree[bugPos].list;
    bool flag = 0;
    int minNum = maxK, cur;

    head = tail = 0;
    vis[bugPos] = 1;
    while(tmpList->next != NULL){
    if(tree[tmpList->next->to].antNum != -1){
    flag = 1;

    //记录相同距离的编号最小的蚂蚁。。
    if(minNum > tree[tmpList->next->to].antNum)
    minNum = tree[tmpList->next->to].antNum;
    }
    queue[tail++] = tmpList->next->to;
    vis[tmpList->next->to] = 1;

    tmpList = tmpList->next;
    }
    //距离为1的节点有蚂蚁
    if(flag){
    tree[antPos[minNum]].antNum = -1;
    antPos[minNum] = bugPos;
    tree[bugPos].antNum = minNum;
    chaseTime[minNum]++;
    return;
    }

    //插桩,即记录BFS每一层结束的位置,以确定蚂蚁到bug的距离。。
    queue[tail++] = -1;

    while(head != tail){
    cur = queue[head++];

    //遇到桩了,说明一层以结束,检查这一层是否有蚂蚁(即离bug最近的蚂蚁),如果没有,继续下一层搜索
    if(cur == -1){
    queue[tail++] = -1;

    if(flag){ //有蚂蚁
    tree[antPos[minNum]].antNum = -1;
    antPos[minNum] = bugPos;
    tree[bugPos].antNum = minNum;
    chaseTime[minNum]++;
    return;
    }
    continue;
    }

    tmpList = &tree[cur].list;
    while(tmpList->next != NULL){
    //已经访问过
    if(vis[tmpList->next->to]){
    tmpList = tmpList->next;
    continue;
    }

    //有蚂蚁
    if(tree[tmpList->next->to].antNum != -1){
    flag = 1;
    if(minNum > tree[tmpList->next->to].antNum)
    minNum = tree[tmpList->next->to].antNum;
    }

    queue[tail++] = tmpList->next->to;
    vis[tmpList->next->to] = 1;

    tmpList = tmpList->next;
    }
    }


    }


    int main(){
    //输入n
    scanf("%d", &n);

    int a, b;
    SList *tmpNode;
    for(int i=0; i<n-1; i++){
    scanf("%d %d", &a, &b);
    tmpNode = &tree[a].list;
    while(tmpNode->next != NULL)
    tmpNode = tmpNode->next;
    tmpNode->next = new SList;
    tmpNode = tmpNode->next;
    tmpNode->to = b;
    tmpNode->next = NULL;

    tmpNode = &tree[b].list;
    while(tmpNode->next != NULL)
    tmpNode = tmpNode->next;
    tmpNode->next = new SList;
    tmpNode = tmpNode->next;
    tmpNode->to = a;
    tmpNode->next = NULL;
    }

    //输入K
    scanf("%d", &k);

    int tmpPos;
    for(int i=0; i<k; i++){
    scanf("%d", &tmpPos);

    antPos[i] = tmpPos;
    tree[tmpPos].antNum = i;
    }

    //输入L
    scanf("%d", &l);

    for(int i=0; i<l; i++){
    memset(vis, 0, sizeof(vis));
    scanf("%d", &tmpPos);
    cal(tmpPos);
    }
    //输出
    for(int i=0; i<k; i++){
    printf("%d %d\n", antPos[i], chaseTime[i]);
    }


    return 0;
    }







  • 相关阅读:
    java中判断文件存在与否
    crontab安装以及定时任务的执行
    su命令学习
    linux中如何查看哪些用户允许登录
    linux中的压缩文件的格式
    R语言学习(瑞士军刀)
    linux下mysql导入导出sql文件
    创建线程池的7种方法
    docker运行tomcat
    Docker之镜像
  • 原文地址:https://www.cnblogs.com/longdouhzt/p/2200314.html
Copyright © 2011-2022 走看看