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