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\n");
        if(t==1)
            printf("LW\n");
        if(t==2)
            printf("MW\n");
        return;
    }
    rep(i-1,u/3);
    int t=u%3;
    if(t==0)
        printf("LM\n");
    if(t==1)
        printf("LW\n");
    if(t==2)
        printf("MW\n");
}
void p(int i,int u)
{
    while(i<=m)
    {
        int t=u%3;
        u/=3;
        i++;
        if(t==0)
            printf("LM\n");
        if(t==1)
            printf("LW\n");
        if(t==2)
            printf("MW\n");
    }
}
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\n");
    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\n");
        if(t==1)
            printf("LW\n");
        if(t==2)
            printf("MW\n");
        return;
    }
    rep(i-1,u/3);
    int t=u%3;
    if(t==0)
        printf("LM\n");
    if(t==1)
        printf("LW\n");
    if(t==2)
        printf("MW\n");
}
void p(int i,int u)
{
    while(i<=m)
    {
        int t=u%3;
        u/=3;
        i++;
        if(t==0)
            printf("LM\n");
        if(t==1)
            printf("LW\n");
        if(t==2)
            printf("MW\n");
    }
}
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\n");
    return 0;
}



 

posted @ 2015-10-17 21:15  abgnwl  阅读(198)  评论(0编辑  收藏  举报