zoj 1022 Parallel Expectations

来源:互联网 发布:阿里巴巴自创数据库 编辑:程序博客网 时间:2024/06/03 21:05

假设目前的状态是已经执行完程序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 insensitiveif (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中的已用长度增加1flag2 = 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;}





原创粉丝点击