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;
    }
    



  • 相关阅读:
    Java实现判断单联通(强连通缩点+拓扑排序)Going from u to v or from v to u
    Java实现判断单联通(强连通缩点+拓扑排序)Going from u to v or from v to u
    Java实现判断单联通(强连通缩点+拓扑排序)Going from u to v or from v to u
    Java实现判断单联通(强连通缩点+拓扑排序)Going from u to v or from v to u
    判断一个窗体是否被完全遮挡(比较有意思,但这招有什么用呢?)
    Delphi中用MessageBox()API函数做倒计时对话框(使用Hook安装CBTHookCallback,计时器更改文字,SetWindowText API真正修改文字,引用未知函数)good
    Delphi&C#代码模拟“显示桌面”的功能(使用CreateOleObject('Shell.Application'))
    LLVM和GCC的区别(LLVM提供了模块化的编译模块,非常有利于重用,以前的编译器都没有做到这一点)
    Delphi产生任务栏图标【TNotifyIconData】
    国内外10大项目外包平台
  • 原文地址:https://www.cnblogs.com/abgnwl/p/6550338.html
Copyright © 2011-2022 走看看