Sicily 1951. Dance King

1951. Dance King

Constraints

Time Limit: 1 secs, Memory Limit: 32 MB

Description

Recently carp has been fascinated by a game named “Dance King”. This game is not quite complex but very interesting; here are some details of the rules:

The game consists of a dancer and one stage where the dancer moves back and forth. And the player is to control the dancer’s moves using a strategy as good as possible.

The stage is divided into n grids (numbered from 1 to n), which are arranged in a row. Before the game starts, the player can make the dancer stand in an arbitrary grid. And after the game has started, at each step, the dancer can stay in a grid, or move to a neighboring grid.

At each step, the dancer can earn a certain number of points according to the current grid where it is. The points not only differ from one grid to another, but also differ from one step to another. For each grid, there is a designated score period. For example, suppose gird 2 has a score period of 3, and the points assigned are 3, 5 and -1. Then if the dancer is in grid 2 at step 1, 4, 7, the dancer can earn 3 points per step; and if the dancer is in grid 2 at step 3, 6, 9,…, then the score each step is -1.

After t steps, the final score of the dancer is the sum of the points earned at each step. As there is an upper limit to the number of steps that the dancer can dance, the goal of the game is to earn as many points as possible within the step number limit. And the player who reaches the highest score using minimum number of steps will be called “Dance King”. Carp is eager to be a “Dance King”, but he is not sure which strategy is the best, can you help him? (Please note that the dancer must dance at least one step)

 

Input

Input may contain several test cases. The first line is a single integer t (1<=t<=20), denoting the number of cases followed. For each test case, the first line consists of two positive integer n and t, (1<=n<=10, 1<=t<=10^16) representing the number of grids and the upper limit of step numbers. The grids are numbered from 1 to n. And then n lines follow, one line for one grid. The i-th (1<=i<=n) line has the form as follows:

K p1 p2 … pk

K(1<=K<=10) is the score period of grid i, and p1,p2,…,pk are the points sequence in one period. Each point is an integer with absolute value no more than 100.

Output

For each test case, output one integer in one line, the highest score in the game the“Dance King” could earn

 

Hint:

<1> Initially the dancer stands in grid 1, and the initial score is 0;

<2> At step 1, the dancer stays in grid 1, the score is 1;

<3> At step 2, the dancer moves to grid 2, the accumulative score is 1+1=2.

<4> At step 3, the dancer moves back to grid 1, and the final score is 1+1+3=5.

Sample Input

12 33 1 -3 32 -2 1

Sample Output

5

// Problem#: 1951
// Submission#: 3591894
// The source code is licensed under Creative Commons Attribution-NonCommercial-ShareAlike 3.0 Unported License
// URI: http://creativecommons.org/licenses/by-nc-sa/3.0/
// All Copyright reserved by Informatic Lab of Sun Yat-sen University
#include <stdio.h>
#include <string.h>
#include <algorithm>
using namespace std;

const long long INF = (1LL << 62);
const int MAXN = 10;
const int MAXK = 10;
const int MAX_CYCLE = 2521;

long long T;
int n;
int p[MAXN][MAXK];
int K[MAXN];
int cycle;

long long f[MAX_CYCLE][MAXN][MAXN];
long long g[65][MAXN][MAXN];
long long h[65][MAXN][MAXN];
long long arb[65][MAXN][MAXN];
long long best[MAXN];

void input() {
    scanf("%d%lld", &n, &T);
    for (int i = 0; i < n; i++) {
        scanf("%d", K + i);
        for (int j = 0; j < K[i]; j++) {
            scanf("%d", &p[i][j]);
        }
    }
}

int gcd(int a, int b) {
    if (b == 0) return a;
    return gcd(b, a % b);
}

int lcm(int a, int b) {
    return a * b / gcd(a, b);
}

int get_cycle() {
    int cycle = 1;
    for (int i = 0; i < n; i++) cycle = lcm(cycle, K[i]);
    return cycle;
}

void dp_in_cycle(int cycle) {
    for (int i = 0; i < n; i++) {
        for (int j = 0; j < n; j++) {
            if (abs(i - j) > 1) f[0][i][j] = -INF;
        }
        f[0][i][i] = p[i][0];
        if (i > 0) f[0][i][i - 1] = p[i - 1][0];
        if (i < n - 1) f[0][i][i + 1] = p[i + 1][0];
    }
    for (int s = 1; s < cycle; s++) {
        for (int i = 0; i < n; i++) {
            for (int j = 0; j < n; j++) {
                f[s][i][j] = f[s - 1][i][j];
                if (j > 0) {
                    f[s][i][j] = max(f[s][i][j], f[s - 1][i][j - 1]);
                }
                if (j < n - 1) {
                    f[s][i][j] = max(f[s][i][j], f[s - 1][i][j + 1]);
                }
                if (f[s][i][j] > -INF) {
                    f[s][i][j] += p[j][s % K[j]];
                }
            }
        }
    }
}

void dp_among_cycles(long long cycles) {
    for (int i = 0; i < n; i++) {
        for (int j = 0; j < n; j++) {
            g[0][i][j] = f[cycle - 1][i][j];
        }
    }
    for (int s = 1; (1LL << s) <= cycles; s++) {
        for (int i = 0; i < n; i++) {
            for (int j = 0; j < n; j++) {
                g[s][i][j] = -INF;
                for (int k = 0; k < n; k++) {
                    if (g[s - 1][i][k] > -INF && g[s - 1][k][j] > -INF) {
                        long long t = g[s - 1][i][k] + g[s - 1][k][j];
                        g[s][i][j] = max(g[s][i][j], t);
                    }
                }
            }
        }
    }
    int bits = 0;
    long long tmp = cycles;
    while (tmp > 0) {
        bits++;
        tmp >>= 1;
    }
    for (int i = 0; i < n; i++) {
        for (int j = 0; j < n; j++) {
            h[bits - 1][i][j] = g[bits - 1][i][j];
        }
    }
    for (int bit = bits - 2; bit >= 0; bit--) {
        if (((1LL << bit) & cycles) > 0LL) {
            for (int i = 0; i < n; i++) {
                for (int j = 0; j < n; j++) {
                    h[bit][i][j] = -INF;
                    for (int k = 0; k < n; k++) {
                        if (h[bit + 1][i][k] > -INF && g[bit][k][j] > -INF) {
                            long long t = h[bit + 1][i][k] + g[bit][k][j];
                            h[bit][i][j] = max(h[bit][i][j], t);
                        }
                    }
                }
            }
        } else {
            for (int i = 0; i < n; i++) {
                for (int j = 0; j < n; j++) {
                    h[bit][i][j] = h[bit + 1][i][j];
                }
            }
        }
    }
    for (int i = 0; i < n; i++) {
        for (int j = 0; j < n; j++) {
            arb[0][i][j] = g[0][i][j];
        }
    }
    for (int bit = 1; bit < bits - 1; bit++) {
        for (int i = 0; i < n; i++) {
            for (int j = 0; j < n; j++) {
                arb[bit][i][j] = arb[bit - 1][i][j];
                arb[bit][i][j] = max(arb[bit][i][j], g[bit][i][j]);
                for (int k = 0; k < n; k++) {
                    if (g[bit][i][k] > -INF && arb[bit - 1][k][j] > -INF) {
                        long long t = g[bit][i][k] + arb[bit - 1][k][j];
                        arb[bit][i][j] = max(arb[bit][i][j], t);
                    }
                }
            }
        }
    }
    for (int i = 0; i < n; i++) best[i] = -INF;
    for (int i = 0; i < n; i++) {
        for (int j = 0; j < n; j++) {
            best[j] = max(best[j], h[0][i][j]);
        }
    }
    if (bits > 1) {
        if ((1LL & cycles) > 0LL) {
            for (int i = 0; i < n; i++) {
                for (int j = 0; j < n; j++) {
                    best[j] = max(best[j], h[1][i][j]);
                }
            }
        }
        for (int bit = 1; bit < bits - 1; bit++) {
            if (((1LL << (bit)) & cycles) > 0LL) {
                for (int i = 0; i < n; i++) {
                    for (int j = 0; j < n; j++) {
                        best[j] = max(best[j], h[bit + 1][i][j]);
                        for (int k = 0; k < n; k++) {
                            if (h[bit + 1][i][k] > -INF && arb[bit - 1][k][j] > -INF) {
                                long long t = h[bit + 1][i][k] + arb[bit - 1][k][j];
                                best[j] = max(best[j], t);
                            }
                        }
                    }
                }
            }
        }
        for (int i = 0; i < n; i++) {
            for (int j = 0; j < n; j++) {
                best[j] = max(best[j], arb[bits - 2][i][j]);
            }
        }
    }
}

long long dp_rest(int rest) {
    long long ans = -INF;
    for (int i = 0; i < n; i++) ans = max(ans, best[i]);
    long long final[MAXN];
    long long old[MAXN];
    for (int i = 0; i < n; i++) old[i] = max(best[i], 0LL);
    for (int s = 0; s < rest; s++) {
        for (int i = 0; i < n; i++) {
            final[i] = old[i];
            if (i > 0) final[i] = max(final[i], old[i - 1]);
            if (i < n - 1) final[i] = max(final[i], old[i + 1]);
            final[i] += p[i][s % K[i]];
            ans = max(ans, final[i]);
        }
        memcpy(old, final, sizeof(old));
    }
    return ans;
}

void solve() {
    cycle = get_cycle();
    dp_in_cycle(cycle);
    long long cycles = T / cycle;
    int rest = T % cycle;
    if (rest < cycle && cycles > 0) {
        cycles--;
        rest += cycle;
    }
    dp_among_cycles(cycles);
    long long ans = dp_rest(rest);
    printf("%lld\n", ans);
}

int main() {
    int casen;
    scanf("%d", &casen);
    while (casen--) {
        input();
        solve();
    }
    return 0;
}                                 


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值