hdu 4576 Robot

题目

Problem Description
Michael has a telecontrol robot. One day he put the robot on a loop with n cells. The cells are numbered from 1 to n clockwise.

At first the robot is in cell 1. Then Michael uses a remote control to send m commands to the robot. A command will make the robot walk some distance. Unfortunately the direction part on the remote control is broken, so for every command the robot will chose a direction(clockwise or anticlockwise) randomly with equal possibility, and then walk w cells forward.
Michael wants to know the possibility of the robot stopping in the cell that cell number >= l and <= r after m commands.
 
Input
There are multiple test cases.
Each test case contains several lines.
The first line contains four integers: above mentioned n(1≤n≤200) ,m(0≤m≤1,000,000),l,r(1≤l≤r≤n).
Then m lines follow, each representing a command. A command is a integer w(1≤w≤100) representing the cell length the robot will walk for this command.
The input end with n=0,m=0,l=0,r=0. You should not process this test case.
 
Output
For each test case in the input, you should output a line with the expected possibility. Output should be round to 4 digits after decimal points.
 
Sample Input
3 1 1 2
1
5 2 4 4
1 2
0 0 0 0
 
Sample Output
0.5000
0.2500
 
题目翻译:
 

迈克尔有一个远程遥控机器人。有一天,他把机器人放在一个有n个格子的环上。单元顺时针编号为1到n。


起初机器人在单元格1中。迈克尔使用遥控器向机器人发送m个命令。命令将使机器人走一段距离。不幸的是,遥控器上的方向部分被毁坏,因此对于每个命令,机器人将以相同的可能性随机选择方向(顺时针或逆时针),然后向前走动w单元。
迈克尔想要知道机器人在m个指令后在单元格 l ~ r 中停止的可能性。

输入
有多个测试用例。
每个测试用例包含几行。
第一行包含四个整数:上述n(1≤n≤200),m(0≤m≤1,000,000),l,r(1≤l≤r≤n)。
然后是m行,每行代表一个命令。命令是整数w(1≤w≤100),表示机器人为此命令行走的单元长度。
输入端的n = 0,m = 0,l = 0,r = 0。您不应该处理此测试用例。

输出
对于输入中的每个测试用例,您应在一行中输出具有预期可能性。小数点后应保留四位数。

分析

推荐学长的blog:【概率期望动态规划】

part 1 状态

状态明显跟上一次的情况有关,与单元格编号有关:

f[步数编号][单元格] = 概率

记得初始化,最初的时候,单元格1概率是1,其余为0

emmm,既然至于上一次有关,那么可以滚动啊

part 2 转移

刷表法 or 填表法

学长说的很清楚了,当前单元格要么来自i - w,要么来自i + w。

part 3 注意事项

关于w万一大于n:这个好办,取余

关于初始化:记得还有这回事

代码

 1 /***********************
 2 User:Mandy.H.Y 
 3 Language:c++
 4 Problem:hdu4576
 5 Algorithm:
 6 ************************/
 7 
 8 //一个概率 + 环形的背包? 
 9 
10 #include<cstdio>
11 #include<cmath>
12 #include<iomanip>
13 #include<algorithm>
14 #include<cstring>
15 
16 using namespace std;
17 
18 const int maxn = 205;
19 const int maxm = 1e6 + 5;
20 
21 int n,m,l,r;
22 double f[2][maxn],ans = 0;
23 
24 template<class T>inline void read(T &x){
25     x = 0;bool flag = 0;char ch = getchar();
26     while(!isdigit(ch)) flag |= ch == '-',ch = getchar();
27     while(isdigit(ch)) x = (x << 1) + (x << 3) + (ch ^ 48),ch = getchar();
28     if(flag) x = -x;
29 }
30 
31 template<class T>void putch(const T x){
32     if(x > 9) putch(x / 10);
33     putchar(x % 10 | 48);
34 }
35 
36 template<class T>void put(const T x){
37     if(x < 0) putchar('-'),putch(-x);
38     else putch(x);
39 }
40 
41 void file(){
42     freopen("4576.in","r",stdin);
43     freopen("4576.out","w",stdout);
44 }
45 
46 int get(int x){
47     if(x < 1) return x + n;
48     if(x > n) return x - n;
49     return x;
50 }
51 
52 void work(){
53     memset(f,0,sizeof(f));//记得清零 
54     f[0][1] = 1;
55     int cur = 1;ans = 0; 
56     for(int i = 1;i <= m; ++ i) {
57         int w;read(w);w %= n;//要对n取模,防止溢出 
58         for(int i = 1;i <= n; ++ i){
59             f[cur][i] = f[cur ^ 1][get(i - w)] * 0.5;
60             f[cur][i] += f[cur ^ 1][get(i + w)] * 0.5;
61         }
62         cur ^= 1;
63     }
64     cur ^= 1;
65     for(int i = l;i <= r; ++ i) ans += f[cur][i];
66 }
67 
68 int main(){
69     
70 //    file();
71 
72     while(scanf("%d%d%d%d",&n,&m,&l,&r)){
73         if((!n) && (!m) && (!l) && (!r)) break;
74         work();
75         printf("%.4lf
",ans);
76     }
77     
78     return 0;
79 }
View Code
非做顽石不可,哪管他敬仰暗唾
原文地址:https://www.cnblogs.com/Mandy-H-Y/p/11402638.html