您的位置:首页 > 其它

Sicily 1005 Roll Playing Games

2016-03-08 16:48 302 查看

Constraints

Time Limit: 1 secs, Memory Limit: 32 MB

Description

Phil Kropotnik is a game maker, and one common problem he runs into is determining the set of dice to use in a game. In many current games, non-traditional dice are often required, that is, dice with more or fewer sides than the traditional 6-sided cube.
Typically, Phil will pick random values for all but the last die, then try to determine specific values to put on the last die so that certain sums can be rolled with certain probabilities (actually, instead of dealing with probabilities, Phil just deals with
the total number of different ways a given sum can be obtained by rolling all the dice). Currently he makes this determination by hand, but needless to say he would love to see this process automated. That is your task.

For example, suppose Phil starts with a 4-sided die with face values 1, 10, 15, and 20 and he wishes to determine how to label a 5-sided die so that there are a) 3 ways to obtain a sum of 2, b) 1 way to obtain a sum of 3, c) 3 ways to obtain 11, d) 4 ways to
obtain 16, and e)1 way to obtain 26. To get these results he should label the faces of his 5-sided die with the values 1, 1, 1, 2, and 6. (For instance, the sum 16 may be obtained as 10 +6 or as 15 +1, with three different "1" faces to choose from on the second
die, for a total of 4 different ways.)

Input

Input will consist of multiple input sets. Each input set will start with a single line containing an integer n indicating the number of dice that are already specified. Each of the next n lines describes one of these dice. Each of these lines will start
with an integer f (indicating the number of faces on the die) followed by f integers indicating the value of each face. The last line of each problem instance will have the form

r m v1 c1 v2 c2 v3 c3 ... vm cm

where r is the number of faces required on the unspecified die, m is the number of sums of interest, v1, ... ,vm are these sums, and c1, ... ,cm are the counts of the desired number of different ways in which to achieve each of the respective sums.

Input values will satisfy the following constraints: 1 <= n <= 20, 3 <= f <= 20, 1 <= m <= 10, and 4 <= r <= 6. Values on the faces of all dice, both the specified ones and the unknown die, will be integers in the range 1 ... 50, and values for the vi's and
ci’s are all non-negative and are strictly less than the maximum value of a 32-bit signed integer.

The last input set is followed by a line containing a single 0; it should not be processed.

Output

For each input set, output a single line containing either the phrase "Final die face values are" followed by the r face values in non-descending order, or the phrase "Impossible" if no die can be found meeting the specifications of the problem. If there
are multiple dice which will solve the problem, choose the one whose lowest face value is the smallest; if there is still a tie, choose the one whose second-lowest face value is smallest, etc.

Sample Input


1
4 1 10 15 20
5 5 2 3 3 1 11 3 16 4 26 1
1
6 1 2 3 4 5 6
6 3 7 6 2 1 13 1
4
6 1 2 3 4 5 6
4 1 2 2 3
3 3 7 9
8 1 4 5 9 23 24 30 38
4 4 48 57 51 37 56 31 63 11
0

Sample Output


Final die face values are 1 1 1 2 6
Impossible
Final die face values are 3 7 9 9


Solution

给出n个骰子,每个骰子的面数和数值都已经给出,然后需要添加一个r面的骰子,使得最后掷骰子的时候满足给定的要求:对于vi有ci种方案。求骰子面值的最小解。自己解析了一下样例之后不是很好思考。要求是针对n+1个骰子的,那个这个要求是不是可以推广到n个呢,一直往下呢?于是就有了dp的方向,把n个骰子时所有的value和对应的方案数求出来,然后进行搜索。搜索的规模是50^6,毫无疑问需要剪枝。怎么剪枝是关键,我思考了很久,n+1个骰子有一个最小值,这个最小值加上当前搜索的值大于要求,且没有达到方案的话,可以进行剪枝。然而还是超时,参考了别人的思路之后,我发现自己遗漏了两个关键的剪枝策略。1.搜索的时候,数列是升序的,也就是不存在1
2 3 1这种解,因为这个和1 1 2 3是等效的。2.若其中任意一个的方案数多于要求,也是需要剪枝的。于是乎,代码就出来了。

#include <stdio.h>
#include <string.h>

int n, r, m, v[15], c[15], res[10], min;
int dp[2][1005];

bool search(int cur, int start)
{
for (int i = 0; i < m; ++i) if (c[i] < 0) return false;
if (cur == r)
{
for (int i = 0; i < m; ++i)
if (c[i] != 0) return false;

return true;
}
for (int i = start; i <= 50; ++i)
{
res[cur] = i;
for (int j = 0; j < m; ++j)
{
if (min + i > v[j] && c[j] != 0) return false;
if (v[j] - i > 0) c[j] -= dp[0][v[j] - i];
}

if (search(cur + 1, i)) return true;
for (int j = 0; j < m; ++j) if (v[j] - i > 0) c[j] += dp[0][v[j] - i];
}

return false;
}

int main()
{
while (scanf("%d", &n) != EOF && n)
{
int f, vf;
memset(dp, 0, sizeof(dp));

for (int i = 1; i <= n; ++i)
{
scanf("%d", &f);

for (int j = 0; j < f; ++j)
{
scanf("%d", &vf);

if (i == 1) dp[1][vf] += 1;
else for (int k = vf; k <= i*50; ++k)
{
dp[1][k] += dp[0][k-vf];
}
}
memcpy(dp[0], dp[1], sizeof(int)*1005);
memset(dp[1], 0, sizeof(int)*1005);
}
scanf("%d%d", &r, &m);
for (int i = 0; i < m; ++i) scanf("%d%d", &v[i], &c[i]);
min = 0;
while(dp[0][min] == 0) min++;

if (search(0, 1))
{
printf("Final die face values are");
for (int i = 0; i < r; ++i) printf(" %d", res[i]);
printf("\n");
}
else printf("Impossible\n");
}

return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签:  sicily 搜索