zoukankan      html  css  js  c++  java
  • Codeforces 585D Lizard Era: Beginning

    D. Lizard Era: Beginning
    time limit per test
    2 seconds
    memory limit per test
    256 megabytes
    input
    standard input
    output
    standard output

    In the game Lizard Era: Beginning the protagonist will travel with three companions: Lynn, Meliana and Worrigan. Overall the game hasn mandatory quests. To perform each of them, you need to take exactly two companions.

    The attitude of each of the companions to the hero is an integer. Initially, the attitude of each of them to the hero of neutral and equal to 0. As the hero completes quests, he makes actions that change the attitude of the companions, whom he took to perform this task, in positive or negative direction.

    Tell us what companions the hero needs to choose to make their attitude equal after completing all the quests. If this can be done in several ways, choose the one in which the value of resulting attitude is greatest possible.

    Input

    The first line contains positive integer n (1 ≤ n ≤ 25) — the number of important tasks.

    Next n lines contain the descriptions of the tasks — the i-th line contains three integers li, mi, wi — the values by which the attitude of Lynn, Meliana and Worrigan respectively will change towards the hero if the hero takes them on the i-th task. All the numbers in the input are integers and do not exceed 107 in absolute value.

    Output

    If there is no solution, print in the first line "Impossible".

    Otherwise, print n lines, two characters is each line — in the i-th line print the first letters of the companions' names that hero should take to complete the i-th task ('L' for Lynn, 'M' for Meliana, 'W' for Worrigan). Print the letters in any order, if there are multiple solutions, print any of them.

    Sample test(s)
    input
    3
    1 0 0
    0 1 0
    0 0 1
    
    output
    LM
    MW
    MW
    
    input
    7
    0 8 9
    5 9 -2
    6 -8 -7
    9 4 5
    -4 -9 9
    -4 5 2
    -6 8 -7
    
    output
    LM
    MW
    LM
    LW
    MW
    LM
    LW
    
    input
    2
    1 0 0
    1 1 0
    
    output
    Impossible


    题意就是

    有3个人 最多25场比赛

    给出每个人参加每场比赛的分数

    每次比赛 你都可以选择两个人 加上那两个人的分数

    最后求一个比赛完所有人分数相同的方案

    如果有多个方案,求分数最大的方案


    一开始看n=25

    3^25太大了 根本做不完 于是就没多想 去搞别的题了


    比赛完后看题目类型 meet-in-the-middle

    据说白书上还有类似的题(自我反省啊!)

    瞬间明白了

    前一半暴力选择方案 扔map里

    后一般暴力 map里查询

    如果当前方案三个人的值分别是x,y,z

    map可以只扔y-x,z-x的值 map的value保存a的值

    如果有相同的key value取最大的

    这样后一半暴力的三个人的值a,b,c

    这样只需要查询 a-b,c-b的值 如果存在 那么value+a即为答案


    这个代码跑了好长时间。。1900+ms 差点超时

    如果直接循环方案对应的三进制数 是不是会更快一点呢?有空试试

    如果不扔map 直接存的话 时间不到1s

    #include<bits/stdc++.h>
    using namespace std;
    const int base=3;
    struct node
    {
        long long y,z;
        node(long long a,long long b)
        {
            y=a;
            z=b;
        }
        bool operator< (const node &head) const
        {
            return head.y==y?head.z<z:head.y<y;
        }
    };
    map<node,int>mp;
    struct info
    {
        int choice;
        long long x;
    }f[2000001];
    int m,n;
    int has=0;
    struct self
    {
        int x,y,z;
    }s[33];
    long long ans;
    int choicex,choicey;
    
    void predfs(int dep,long long x,long long y,long long z,int choice)
    {
    //for(int kk=1;kk<dep;kk++)
    //cout<<"  ";
    //cout<<"dep="<<dep<<" x="<<x<<" y="<<y<<" z="<<z<<" choice="<<choice<<endl;
        if(dep==n+1)
        {
    //cout<<" predfs dep="<<dep-1<<" "<<x<<" "<<y<<" "<<z<<endl;
            y-=x;
            z-=x;
            node t=node(y,z);
            if(mp.find(t)!=mp.end())
            {
                int pos=mp[t];
                if(f[pos].x<x)
                {
                    f[pos].x=x;
                    f[pos].choice=choice;
                }
            }
            else
            {
                has++;
                mp[t]=has;
                f[has].x=x;
                f[has].choice=choice;
    //cout<<"            add "<<y<<" "<<z<<"  base="<<x<<" choice="<<choice<<endl;
            }
            return;
        }
        //1 2    1 3    2 3
        for(int k=0;k<=2;k++)
        {
            if(k==0)
            {
                predfs(dep+1,x+s[dep].x,y+s[dep].y,z,choice*3+k);
            }
            if(k==1)
            {
                predfs(dep+1,x+s[dep].x,y,z+s[dep].z,choice*3+k);
            }
            if(k==2)
            {
                predfs(dep+1,x,y+s[dep].y,z+s[dep].z,choice*3+k);
            }
        }
    }
    
    void lowdfs(int dep,long long x,long long y,long long z,int choice)
    {
        if(dep==n)
        {
            y-=x;
            z-=x;
            node t=node(-y,-z);
            if(mp.find(t)!=mp.end())
            {
                int pos=mp[t];
    //cout<<" pre="<<f[pos].x<<" low="<<x<<endl;
                {
                    if(f[pos].x+x>ans)
                    {
                        ans=f[pos].x+x;
    //cout<<" ans="<<ans<<endl;
                        choicex=f[pos].choice;
                        choicey=choice;
                    }
                }
            }
            return;
        }
    
        for(int k=0;k<=2;k++)
        {
            if(k==0)
            {
                lowdfs(dep-1,x+s[dep].x,y+s[dep].y,z,choice*3+k);
            }
            if(k==1)
            {
                lowdfs(dep-1,x+s[dep].x,y,z+s[dep].z,choice*3+k);
            }
            if(k==2)
            {
                lowdfs(dep-1,x,y+s[dep].y,z+s[dep].z,choice*3+k);
            }
        }
    }
    
    void rep(int i,int u)
    {
        if(i==1)
        {
            int t=u%3;
            if(t==0)
                printf("LM
    ");
            if(t==1)
                printf("LW
    ");
            if(t==2)
                printf("MW
    ");
            return;
        }
        rep(i-1,u/3);
        int t=u%3;
        if(t==0)
            printf("LM
    ");
        if(t==1)
            printf("LW
    ");
        if(t==2)
            printf("MW
    ");
    }
    void p(int i,int u)
    {
        while(i<=m)
        {
            int t=u%3;
            u/=3;
            i++;
            if(t==0)
                printf("LM
    ");
            if(t==1)
                printf("LW
    ");
            if(t==2)
                printf("MW
    ");
        }
    }
    void print(int l,int r)
    {
        //cout<<ans<<endl;
        rep(n,l);
        p(n+1,r);
    }
    int main()
    {
        ans=-1e14;
        scanf("%d",&m);
        for(int i=1;i<=m;i++)
            scanf("%d%d%d",&s[i].x,&s[i].y,&s[i].z);
        if(m%2==0)
            n=m/2;
        else
            n=m/2+1;
        //cout<<"n="<<n<<endl;
        predfs(1,0,0,0,0);
        lowdfs(m,0,0,0,0);
        //cout<<ans<<endl;
        if(ans!=-1e14)
            print(choicex,choicey);
        else
            printf("Impossible
    ");
        return 0;
    }


    直接存+排序+二分

    980ms

    #include<bits/stdc++.h>
    using namespace std;
    struct node
    {
        long long y,z;
        long long x;
        int choice;
    };
    node g[2000001];
    int cmp(node head,node a)
    {
        if(head.y!=a.y)
            return head.y<a.y;
        if(head.z!=a.z)
            return head.z<a.z;
        return head.x>a.x;
    }
    
    struct info
    {
        int choice;
        long long x;
    }f[2000001];
    int m,n;
    int has=0;
    struct self
    {
        int x,y,z;
    }s[33];
    long long ans;
    int choicex,choicey;
    
    int ipow(int i,int k)
    {
        if(k==0)
            return 1;
        return i*ipow(i,k-1);
    }
    void add(long long &a,long long &b,long long &c,int k,int i)
    {
        if(k==0)
        {
            a+=s[i].x;
            b+=s[i].y;
        }
        if(k==1)
        {
            a+=s[i].x;
            c+=s[i].z;
        }
        if(k==2)
        {
            b+=s[i].y;
            c+=s[i].z;
        }
    }
    
    void add(int u)
    {
        int v=u;
        long long x=0,y=0,z=0;
        for(int i=n;i>=1;i--)
        {
            add(x,y,z,v%3,i);
            v/=3;
        }
        y-=x;
        z-=x;
        has++;
        g[has].x=x;
        g[has].y=y;
        g[has].z=z;
        g[has].choice=u;
    }
    int bs(long long y,long long z)
    {
        int l=1,r=has,mid,ret=0;
        while(l<=r)
        {
            mid=(l+r)>>1;
            if(g[mid].y>y||(g[mid].y==y && g[mid].z>=z))
            {
                ret=mid;
                r=mid-1;
            }
            else
                l=mid+1;
        }
        if(g[ret].y==y && g[ret].z==z)
            return ret;
        else
            return 0;
    }
    void calc(int u)
    {
        int v=u;
        long long x=0,y=0,z=0;
        for(int i=n+1;i<=m;i++)
        {
            add(x,y,z,v%3,i);
            v/=3;
        }
        y-=x;
        z-=x;
        int pos=bs(-y,-z);
        if(pos!=0)
            if(g[pos].x+x>ans)
            {
                ans=g[pos].x+x;
                choicex=g[pos].choice;
                choicey=u;
            }
    }
    void rep(int i,int u)
    {
        if(i==1)
        {
            int t=u%3;
            if(t==0)
                printf("LM
    ");
            if(t==1)
                printf("LW
    ");
            if(t==2)
                printf("MW
    ");
            return;
        }
        rep(i-1,u/3);
        int t=u%3;
        if(t==0)
            printf("LM
    ");
        if(t==1)
            printf("LW
    ");
        if(t==2)
            printf("MW
    ");
    }
    void p(int i,int u)
    {
        while(i<=m)
        {
            int t=u%3;
            u/=3;
            i++;
            if(t==0)
                printf("LM
    ");
            if(t==1)
                printf("LW
    ");
            if(t==2)
                printf("MW
    ");
        }
    }
    void print(int l,int r)
    {
        rep(n,l);
        p(n+1,r);
    }
    
    int main()
    {
        ans=-1e14;
        scanf("%d",&m);
        for(int i=1;i<=m;i++)
            scanf("%d%d%d",&s[i].x,&s[i].y,&s[i].z);
        if(m%2==0)
            n=m/2;
        else
            n=m/2+1;
        for(int i=0;i<ipow(3,n);i++)
            add(i);
        sort(g+1,g+has+1,cmp);
        for(int i=0;i<ipow(3,m-n);i++)
            calc(i);
    
        if(ans!=-1e14)
            print(choicex,choicey);
        else
            printf("Impossible
    ");
        return 0;
    }
    



  • 相关阅读:
    mvc 注册脚本的其他方法
    如何将html代码转换为Xml并生成Dom树
    用TFIDF值来判断词的重要性
    oem key
    vs2010 下的ado.net 实体模型创建数据库时datetime 类型的问题
    asp.net mvc 动态注册脚本
    ASP.NET 中如何对生成的 HTML 内容流进行控制
    C# 子窗体调用父窗体的方法
    layui 弹出新页面
    winform excel导入进度条
  • 原文地址:https://www.cnblogs.com/abgnwl/p/6550338.html
Copyright © 2011-2022 走看看