Sicily 1005 Roll Playing Games
2016-03-08 16:48
302 查看
Constraints
Time Limit: 1 secs, Memory Limit: 32 MBDescription
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 startwith 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 thereare 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;
}
相关文章推荐
- 搜狗百度360市值齐跌:搜索引擎们陷入集体焦虑?
- 本人即将筹备败家日志,敬请期待!
- IE:使用搜索助手
- C++深度优先搜索的实现方法
- 基于文本的搜索
- php实现搜索一维数组元素并删除二维数组对应元素的方法
- 使用Sphinx对索引进行搜索
- asp 多关键词搜索的简单实现方法
- C#使用foreach语句搜索数组元素的方法
- WordPress中用于获取搜索表单的PHP函数使用解析
- JavaScript中数组的排序、乱序和搜索实现代码
- jquery ztree实现树的搜索功能
- C#编程实现Excel文档中搜索文本内容的方法及思路
- sqlserver中在指定数据库的所有表的所有列中搜索给定的值
- 可以用来搜索当前页面内容的js代码
- 全文搜索和替换
- javascript搜索自动提示功能的实现第1/3页
- iOS应用中UISearchDisplayController搜索效果的用法
- mysql 模糊搜索的方法介绍
- C#搜索文字在文件及文件夹中出现位置的方法