CodeForces 585D Lizard Era: Beginning

CodeForces 585D Lizard Era: Beginning

题目描述:

N 个任务和 3 个随从,每个任务可以选择两个随从,并且相应地增加他们的好感度(可能为负数),输出一个方案,使得结束之后,所有随从的好感度相等并且尽可能大。

题解:

枚举前一半可能出现的 3 个好感度,用一个 3 进制数表示操作序列,把它们存在一个哈希表里;再枚举剩下的一半,从哈希表里查找。

题目链接: vjudge 原网站

代码:

#include <cstdio>
#include <cstdlib>
#include <climits>
#include <algorithm>
using namespace std;

#define MAXN 27
#define MAXK 2000007

const long long INF = INT_MAX / 3;

static int N, M, val[MAXN][3];
static long long seq1, seq2, sum = -INF, pw3[MAXN] = {1};

namespace HashTable
{
    const long long BASE = 500000000LL;
    const long long MOD = 9999993LL;

    static int G = 1, head[MOD + 3], next[MAXK], val[MAXK][3];
    static long long seq[MAXK];

    inline void insert(int x, int y, int z, long long p)
    {
        int k = (x - y + BASE) % MOD;
        for (int i = head[k]; i; i = next[i])
            if (val[i][0] == x && val[i][1] == y && val[i][2] == z)
                return ;
        val[G][0] = x; val[G][1] = y; val[G][2] = z; seq[G] = p; next[G] = head[k]; head[k] = G++;
    }

    inline void update_value(int x, int y, int z, long long p, long long &rs, long long &rp1, long long &rp2)
    {
        int k = (y - x + BASE) % MOD;
        for (int i = head[k]; i; i = next[i])
            if (val[i][1] - val[i][2] == z - y)
                if (val[i][0] + x > rs) rs = val[i][0] + x, rp1 = seq[i], rp2 = p;
    }
}

void dfs1(int k, int x, int y, int z, long long p)
{
    if (k == M) return HashTable::insert(x, y, z, p);
    dfs1(k + 1, x + val[k][0], y + val[k][1], z, p * 3 + 0);
    dfs1(k + 1, x + val[k][0], y, z + val[k][2], p * 3 + 1);
    dfs1(k + 1, x, y + val[k][1], z + val[k][2], p * 3 + 2);
}

void dfs2(int k, int x, int y, int z, long long p)
{
    if (k == N) return HashTable::update_value(x, y, z, p, sum, seq1, seq2);
    dfs2(k + 1, x + val[k][0], y + val[k][1], z, p * 3 + 0);
    dfs2(k + 1, x + val[k][0], y, z + val[k][2], p * 3 + 1);
    dfs2(k + 1, x, y + val[k][1], z + val[k][2], p * 3 + 2);
}

int main()
{
    scanf("%d", &N); M = N / 2;
    for (int i = 1; i <= N; i++) pw3[i] = pw3[i-1] * 3;
    for (int i = 0; i < N; i++)
        scanf("%d%d%d", &val[i][0], &val[i][1], &val[i][2]);
    dfs1(0, 0, 0, 0, 0);
    dfs2(M, 0, 0, 0, 0);
    if (sum == -INF)
        return puts("Impossible"), 0;
    for (int i = 0; i < M; i++)
    {
        int k = seq1 / pw3[M - i - 1] % 3;
        if (!k)
            puts("LM");
        else if (k == 1)
            puts("LW");
        else
            puts("MW");
    }
    for (int i = M; i < N; i++)
    {
        int k = seq2 / pw3[N - i - 1] % 3;
        if (!k)
            puts("LM");
        else if (k == 1)
            puts("LW");
        else
            puts("MW");
    }
    return 0;
}

提交记录(AC / Total = 1 / 2):

Run IDRemote Run IDTime(ms)Memory(kb)ResultSubmit Time
87753182635210524987952RE2017-04-14 15:44:50
87753762635215017187956AC2017-04-14 15:49:14
  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值