您的位置:首页 > 其它

zoj 1022 Parallel Expectations

2017-06-25 20:46 246 查看
假设目前的状态是已经执行完程序1的第i条指令,并且执行完了程序2的第j条指令,那么记到达该状态的概率为p[i][j]

那么到达p[i][j]状态有两种可能,一种是程序1已经执行了i-1条指令,程序2执行了j条指令,另一种是程序1执行了i条指令,程序2执行了j-1条指令

所以我们有

if (i < p_line1&&j < p_line2){
p1 = 0.5*prob[i - 1][j]; p2 =0.5* prob[i][j - 1];
}
else if (i < p_line1){//如果程序2全部执行完了,那么执行程序1的概率不变了
p1 = prob[i - 1][j]; p2 = 0.5*prob[i][j - 1];
}
else if (j < p_line2){//如果程序1全部执行完了,那么执行程序2的概率不再变化
p1 = prob[i - 1][j] * 0.5; p2 = prob[i][j - 1];
}
else{
p1 = prob[i - 1][j]; p2 = prob[i][j - 1];
}
prob[i][j] = p1 + p2;

p_line1表示的是程序1的总指令条数,p_line2表示的程序2的总指令条数

源代码(附注释)如下:

#include<iostream>
#include<string>
#include<vector>
#include<algorithm>
#include<cstdio>
using namespace std;

int t;
int number1, number2;
string word[3];
int line1, line2;

typedef struct{
bool is_const;
string name;
double value;
}var;

typedef struct{
int index1;
int index2;
char op;
}com;
com command[2][110];
var variable[150];
double prob[110][110],p1,p2,p;
double excute[110][110][40];

void resolve2(int aim,int source,int machine,char op,int current){
command[machine][current].index1 = aim;
command[machine][current].index2 = source;
command[machine][current].op = op;
}

void resolve(int flag1,int flag2,int flag3,int machine,char op,int current){
int R1 = 2 * machine;
int R2 = 2 * machine + 1;
resolve2(R1,flag2,machine,':',4*current+1);//记录每一条机器指令的操作数以及对应的操作符,便于后面的分析
resolve2(R2,flag3,machine,':',4*current+2);
resolve2(R1,R2,machine,op,4*current+3);
resolve2(flag1,R1,machine,':',4*current+4);
}

int store_variable(string name,int &cur){
if (name[0] >= '0'&&name[0] <= '9'){
int value = 0;
for (int i = 0; i < name.size(); i++){
value = value * 10 + (name[i]-'0');
}
variable[cur].is_const = true;
variable[cur].name = "const";
variable[cur].value = value;
return cur++;
}
else{
for (int i = 0; i < cur; i++){
if (variable[i].is_const) continue;
if (variable[i].name == name) return i;
}
variable[cur].is_const = false;
variable[cur].name = name;
variable[cur].value = 0;
return cur++;
}
}

void init(){//variable中的前四个元素用来存储寄存器
for (int i = 0; i < 4; i++){
variable[i].is_const = true;
variable[i].name = "Rx";
variable[i].value = 0;
}
}

int read_command(int machine,int& number3){//machine用来表示程序的编号
//number用来标识从第几个变量开始存储
string s1;
int lines = 0;
while (getline(cin, s1)){
if (s1 == "") continue;//如果当前读入的是回车字符,则继续读入
if (s1 == "END") break;
string s="";
for (int i = 0; i < s1.size(); i++){//去掉读入的字符串中的空格符,并且将所有的字母都统一成大写形式
//便于后续的管理,注意题目中的Case insensitive
if (s1[i] == ' ') continue;
if (s1[i] >= 'a'&&s1[i] <= 'z'){
s1[i] = toupper(s1[i]);
}
s+=s1[i];
}
lines++;
int index1, index2, index3;
for (int i = 0; i < s.size(); i++){
if (s[i] == ':'){//记录冒号的位置
index1 = i;
}
else if (s[i] == '+'||s[i]=='-'){//记录符号的位置
index2 = i;
break;
}
}
word[0] = s.substr(0,index1);//提取变量名
word[1] = s.substr(index1+2,index2-index1-2);
word[2] = s.substr(index2+1);
int flag1, flag2, flag3;
flag1 = store_variable(word[0], number3);//如果变量在variabel数组中已经存在,那么就直接返回下标,否则就在variable中找一个位置存储
//同时让variable中的已用长度增加1
flag2 = store_variable(word[1], number3);
flag3 = store_variable(word[2], number3);
resolve(flag1, flag2, flag3, machine, s[index2],lines-1);//将每行代码翻译成为对应的四条机器指令
}
return lines;
}

void cal(double* temp11,int index, int machine){
int index1 = command[machine][index].index1;
int index2 = command[machine][index].index2;
if (command[machine][index].op == ':'){
temp11[index1] = temp11[index2];
}
else if (command[machine][index].op == '+'){
temp11[index1] += temp11[index2];
}
else if (command[machine][index].op == '-'){
temp11[index1] -= temp11[index2];
}
}

bool compare(var a,var b){
if (a.is_const != b.is_const) return a.is_const > b.is_const;
else{
return a.name < b.name;
}
}

void dp(int p_line1,int p_line2){
prob[0][0] = 1;
for (int i = 0; i < number2; i++){//在所有代码开始执行之前保存已有的每一个常量和变量的值
excute[0][0][i] = variable[i].value;
}
for (int i = 1; i <= p_line1; i++){//仅仅开始执行第一段程序的每一行所出现的结果都保存
prob[i][0] = 0.5*prob[i-1][0];
for (int k = 0; k < number2; k++) excute[i][0][k] = excute[i-1][0][k];
cal(excute[i][0],i,0);
}
for (int j = 1; j <= p_line2; j++){//仅仅开始执行第二段程序的每一行所出现的结果都保存
prob[0][j] = 0.5*prob[0][j-1];
for (int k = 0; k < number2; k++) excute[0][j][k] = excute[0][j-1][k];
cal(excute[0][j],j,1);
}
double temp1[40], temp2[40];//分析交叉执行的情况
for (int i = 1; i <= p_line1; i++){
for (int j = 1; j <= p_line2; j++){
for (int k = 0; k < number2; k++){
temp1[k] = excute[i - 1][j][k];
temp2[k] = excute[i][j - 1][k];
}
cal(temp1, i, 0);
cal(temp2, j, 1);
if (i < p_line1&&j < p_line2){ p1 = 0.5*prob[i - 1][j]; p2 =0.5* prob[i][j - 1]; }
else if (i < p_line1){
p1 = prob[i - 1][j]; p2 = 0.5*prob[i][j - 1];
}
else if (j < p_line2){
p1 = prob[i - 1][j] * 0.5; p2 = prob[i][j - 1];
}
else{
p1 = prob[i - 1][j]; p2 = prob[i][j - 1];
}
prob[i][j] = p1 + p2;
for (int k = 0; k < number2; k++){
excute[i][j][k] = (p1*temp1[k] + p2*temp2[k]) / (prob[i][j]);
}
}
}
for (int k = 0; k < number2; k++){//利用variable保存交叉执行的最终结果
variable[k].value = excute[p_line1][p_line2][k];
}
sort(variable+4,variable+number2,compare);//排序
int start = 4;
while (start < number2&&variable[start].is_const) start++;
for (int i = start; i < number2; i++) printf("%.4lf\n",variable[i].value);//输出最终结果
}

int main(){
cin >> t;//读入Case的数量
string temp;
getline(cin,temp);//消除回车符
while (t--){
init();//初始化,在所定义的variable中,前两个用作第一个程序的寄存器,后两个用作第二个程序的寄存器
number1 = 4;//后面变量的记录从第四个开始
line1 = read_command(0,number1);//开始读入第一个程序
number2 = number1;
line2 = read_command(1,number2);//开始读入第二个程序
dp(4*line1,4*line2);//开始进行计算
if (t) printf("\n");
}
return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: