POJ 1487:Single-Player Games 浮点数高斯消元
Time Limit: 1000MS | Memory Limit: 10000K | |
Total Submissions: 1287 | Accepted: 362 |
Description
probably responsible for more wasted hours in offices around the world than any other game.
The goal of a single-player game is usually to make ``moves'' until one reaches a final state of the game, which results in a win or loss, or a score assigned to that final state. Most players try to optimize the result of the game by employing good strategies.
In this problem we are interested in what happens if one plays randomly. After all, these games are mostly used to waste time, and playing randomly achieves this goal as well as any other strategy.
Games can very compactly represented as (possibly infinite) trees. Every node of the tree repre- sents a possible game state. The root of the tree corresponds to the starting position of the game. For an inner node, its children are the game states to which
one can move in a single move. The leaf nodes are the final states, and every one of them is assigned a number, which is the score one receives when ending up at that leaf.
Trees are defined using the following grammar.
Definition ::= Identifier "=" RealTree
RealTree ::= "("Tree+")"
Tree ::= Identifier | Integer | "("Tree+")"
Identifier ::= a|b|...|z
Integer ∈ {...,-3,-2,-1,0,1,2,3,...,}
By using a Definition, the RealTree on the right-hand side of the equation is assigned to the Identifier on the left. A RealTree consists of a root node and one or more children, given as a sequence enclosed in brackets. And a Tree is either
. the tree represented by a given Identifier, or
. a leaf node, represented by a single Integer, or
. an inner node, represented by a sequence of one or more Trees (its children), enclosed in brackets.
Your goal is to compute the expected score, if one plays randomly, i.e. at each inner node selects one of the children uniformly at random. This expected score is well-defined even for the infinite trees definable in our framework as long as the probability
that the game ends (playing randomly) is 1.
Input
the definitions of these identifiers (in the order a, b, ...). Each definition may contain arbitrary whitespace (but of course there will be no spaces within a single integer). The right hand side of a definition will contain only identifiers from the first
n lowercase letters. The inputs ends with a test case starting with n = 0. This test case should not be processed.
Output
expected score (when playing randomly). This value should be exact to three digits to the right of the decimal point.
If the game described by the variable does not end with probability 1, print ``Expected score of id undefined'' instead. Output a blank line after each test case.
Sample Input
1
a = ((1 7) 6 ((8 3) 4))
2
a = (1 b)
b = (4 a)
1
a = (a a a)
0
Sample Output
Game 1
Expected score for a = 4.917 Game 2
Expected score for a = 2.000
Expected score for b = 3.000 Game 3
Expected score for a undefined
题意是给出一个树,然后树上的根节点有相应的值,所有根节点 对应的值*树到达该根节点的概率 相加就是1。用深搜的方法列方程,每一个字符列一个方程,最后用高斯消元解方程。
这题出得很严谨,注意精度。
今天出了各种问题,这道题调了差不多4个小时。。。
#pragma warning(disable:4996)
#include <iostream>
#include <algorithm>
#include <cmath>
#include <vector>
#include <stdlib.h>
#include <string.h>
#include <string>
#include <cstring>
using namespace std; #define eps 1e-6 int n, p, len;
char s[350];
int free_x[500];
double x[500];
double val[500][500]; inline double zero(double x)
{
if (fabs(x) > eps)return x;
return 0;
}
int Gauss(int equ, int var)
{
int i, j, k;
int max_r;//当前这列绝对值最大的行
int col;//当前处理的列
double tb;
double temp; for (int i = 0; i <= var; i++)
{
x[i] = 0;
free_x[i] = 1;
}
//转换为阶梯阵
col = 0;//当前处理的列
for (k = 0; k < equ&&col < var; k++, col++)
{
//枚举当前处理的行
//找到该col列元素绝对值最大的那行与第k行交换.(为了在除法时减少误差)
max_r = k;
for (i = k + 1; i < equ; i++)
{
if (fabs(val[i][col])>fabs(val[max_r][col]))
max_r = i;
}
if (max_r != k)
{//与第k行交换
for (j = k; j < var + 1; j++)
swap(val[k][j], val[max_r][j]);
}
if (fabs(val[k][col]) < eps)
{
k--;
continue;
}
for (i = k + 1; i < equ; i++)
{//枚举要删去的行
if (fabs(val[i][col]) > eps)
{
tb = val[i][col] / val[k][col];
for (j = col; j < var + 1; j++)
{
val[i][j] = (val[i][j] - val[k][j] * tb);
}
}
}
} //无解的情况
for (i = k; i < equ; i++)
{
if (val[i][col] > eps)
return -1;
} if (k < equ)
{
//注释处为求多解的自由变量
// 首先,自由变元有n - k个,即不确定的变元至少有n - k个.
int num = 0, freeidx;
for (i = k - 1; i >= 0; --i)
{
num = 0;// 用于判断该行中的不确定的变元的个数,如果超过1个,则无法求解,它们仍然为不确定的变元.
double tmp = val[i][n];
// 第i行一定不会是(0, 0, ..., 0)的情况,因为这样的行是在第k行到第m行.
// 同样,第i行一定不会是(0, 0, ..., a), a != 0的情况,这样的无解的.
for (j = 0; j < n; ++j)
{
if (fabs(val[i][j])>eps && free_x[j])
{
num++;
freeidx = j;
}
}
if (num > 1) continue; // 无法求解出确定的变元.
// 说明就只有一个不确定的变元free_index,那么可以求解出该变元,且该变元是确定的.
tmp = val[i][n];
for (j = 0; j < n; ++j)
{
if (fabs(val[i][j])>eps && j != freeidx) tmp -= val[i][j] * x[j];
}
x[freeidx] = tmp / val[i][freeidx];
free_x[freeidx] = 0;
}
return n - k;
} for (i = var - 1; i >= 0; i--)
{
temp = val[i][var];
for (j = i + 1; j < var; j++)
{
if (val[i][j])
{
temp = temp - val[i][j] * x[j];
}
}
x[i] = temp / val[i][i];
}
return 0;
} void dfs(double *a)
{
int cnt = 0;
while (s[p] != ')')
{
if (s[p] == ' ')
{
p++;
}
else if (s[p] == '(')
{
double b[50];
p++; memset(b, 0, sizeof(b));
dfs(b);
cnt++;
for (int k = 0; k <= n; k++)
{
a[k] += b[k];
}
}
else if (s[p] >= '0'&&s[p] <= '9')
{
cnt++;
int num = 0;
while (s[p] >= '0'&&s[p] <= '9')
{
num = num * 10;
num = num + s[p] - '0';
p++;
}
a[n] += num;
}
else if (s[p] == '-')
{
cnt++;
int num = 0;
p++;
while (s[p] >= '0'&&s[p] <= '9')
{
num = num * 10;
num = num + s[p] - '0';
p++;
}
a[n] -= num;
}
else if (s[p] >= 'a'&&s[p] <= 'z')
{
cnt++;
a[s[p] - 'a']++;
p++;
}
} if (cnt)
{
for (int k = 0; k <= 27; k++)
{
a[k] = a[k] / cnt;
}
}
p++;
return;
} int main()
{
//freopen("i.txt", "r", stdin);
//freopen("o.txt", "w", stdout); int i, k, ans;
int itest = 0;
while (scanf("%d", &n) != EOF)
{
if (n == 0)
break; getchar();
memset(val, 0, sizeof(val)); printf("Game %d\n", ++itest);
for (i = 0; i < n; i++)
{
gets_s(s);//VS2015用gets_s代替了get p = 0;
while (s[p] != '(')
p++;
p++;
dfs(val[i]);
for (k = 0; k < n; k++)
val[i][k] = -val[i][k];
val[i][i]++;
}
ans = Gauss(n, n);
for (k = 0; k < n; k++)
{
if (ans == -1)
{
printf("Expected score for %c undefined\n", k + 'a');
}
else if (ans == 0)
{
printf("Expected score for %c = %.3lf\n", k + 'a',x[k]);
}
else
{
if (free_x[k])
printf("Expected score for %c undefined\n", k + 'a');
else
printf("Expected score for %c = %.3lf\n", k + 'a', x[k]);
} }
printf("\n");
}
//system("pause");
return 0;
}
POJ 1487:Single-Player Games 浮点数高斯消元的更多相关文章
- 【POJ 1830】 开关问题 (高斯消元)
开关问题 Description 有N个相同的开关,每个开关都与某些开关有着联系,每当你打开或者关闭某个开关的时候,其他的与此开关相关联的开关也会相应地发生变化,即这些相联系的开关的状态如果原来为 ...
- 【POJ】2947 Widget Factory(高斯消元)
http://poj.org/problem?id=2947 各种逗啊..还好1a了.. 题意我就不说了,百度一大把. 转换为mod的方程组,即 (x[1,1]*a[1])+(x[1,2]*a[2]) ...
- POJ 1681 Painter's Problem 【高斯消元 二进制枚举】
任意门:http://poj.org/problem?id=1681 Painter's Problem Time Limit: 1000MS Memory Limit: 10000K Total ...
- POJ 3185 The Water Bowls(高斯消元-枚举变元个数)
题目链接:http://poj.org/problem?id=3185 题意:20盏灯排成一排.操作第i盏灯的时候,i-1和i+1盏灯的状态均会改变.给定初始状态,问最少操作多少盏灯使得所有灯的状态最 ...
- POJ 1222 EXTENDED LIGHTS OUT(高斯消元)
[题目链接] http://poj.org/problem?id=1222 [题目大意] 给出一个6*5的矩阵,由0和1构成,要求将其全部变成0,每个格子和周围的四个格子联动,就是说,如果一个格子变了 ...
- POJ 1222 EXTENDED LIGHTS OUT(高斯消元)题解
题意:5*6的格子,你翻一个地方,那么这个地方和上下左右的格子都会翻面,要求把所有为1的格子翻成0,输出一个5*6的矩阵,把要翻的赋值1,不翻的0,每个格子只翻1次 思路:poj 1222 高斯消元详 ...
- POJ 1681 Painter's Problem(高斯消元+枚举自由变元)
http://poj.org/problem?id=1681 题意:有一块只有黄白颜色的n*n的板子,每次刷一块格子时,上下左右都会改变颜色,求最少刷几次可以使得全部变成黄色. 思路: 这道题目也就是 ...
- POJ 1222 EXTENDED LIGHTS OUT(高斯消元解XOR方程组)
http://poj.org/problem?id=1222 题意:现在有5*6的开关,1表示亮,0表示灭,按下一个开关后,它上下左右的灯泡会改变亮灭状态,要怎么按使得灯泡全部处于灭状态,输出方案,1 ...
- 【POJ】1830 开关问题(高斯消元)
http://poj.org/problem?id=1830 高斯消元无解的条件:当存在非法的左式=0而右式不等于0的情况,即为非法.这个可以在消元后,对没有使用过的方程验证是否右式不等于0(此时因为 ...
随机推荐
- Centos610快照克隆后网络配置
VMware中安装的Centos610快照并克隆后网络配置 1.网卡配置 vi /etc/sysconfig/network-scripts/ifcfg-eth0 DEVICE=eth0 HWADDR ...
- VScode Vim插件快速上手与配置
快速安装: 打开market place,搜索vim即可安装. 基本改建与配置说明: 方向键: 用I k j l表示光标上下左右,需要编辑visual mode和normal mode { " ...
- winform Anchor和Dock属性
在设计窗体时,这两个属性特别有用,如果用户认为改变窗口的大小并不容易,应确保窗口看起来不显得很乱,并编写许多代码行来达到这个目的,许多程序解决这个问题是地,都是禁止给窗口重新设置大小,这显然是解决问题 ...
- java 协程
协程是比线程更轻量级的程序处理单元,也可以说是运行在线程上的线程,由自己控制 1.适用于被阻塞的,且需要大量并发的场景. 2.不适用于,大量计算的多线程,遇到此种情况,更好实用线程去解决. 虽然Jav ...
- python opencv:使用滑动条做调色板
cv2.getTrackbarPos() 函数的 一个参数是滑动条的名字, 第二个参数是滑动条被放置窗口的名字, 第三个参数是滑动条的默认位置. 第四个参数是滑动条的最大值, 第五个函数是回调函数,每 ...
- Bugku - CTF加密篇之聪明的小羊(一只小羊翻过了2个栅栏)
聪明的小羊 一只小羊翻过了2个栅栏 KYsd3js2E{a2jda}
- 学校实训作业:Java爬虫(WebMagic框架)的简单操作
项目名称:java爬虫 项目技术选型:Java.Maven.Mysql.WebMagic.Jsp.Servlet 项目实施方式:以认知java爬虫框架WebMagic开发为主,用所学java知识完成指 ...
- JS打开浏览器新窗口
window.open(URL,name,features,replace); 参数 描述 URL 一个可选的字符串,声明了要在新窗口中显示的文档的 URL.如果省略了这个参数,或者它的值是空字符串, ...
- 洛谷 P3009 [USACO11JAN]利润Profits
嗯... 题目链接:https://www.luogu.org/problemnew/show/P3009 这是DP的另一个功能,求最大子段和(最大子段和模板:https://www.luogu.or ...
- Hive的mysql安装配置
一.MySQL的安装 Hive的数据,是存在HDFS里的.此外,hive有哪些数据库,每个数据库有哪些表,这样的信息称之为hive的元数据信息. 元数据信息不存在HDFS,而是存在关系型数据库里,hi ...