是一道水题,其最重要的部分在于字符串处理建立树。
代码如下:
#include"stdafx.h"
#include<iostream>
#include<string>
#include<stdio.h>
#include <iomanip>
#include<set>
using namespace std;
#define LEFTBRACKET '('
#define RIGHTBRACKET ')'
const int MAX = 1000;
class Node{
public:
Node *left, *right;
string feature;
bool leaf;
double weight;
Node() {
left = right = 0;
leaf = true;
weight = 0.0;
}
void set(double, bool, string);
void set(double);
};
class Stack{
private:
Node *a[MAX];
int top;
public:
Stack():top(-1){}
void Push(Node *);
void Pop();
Node *Top();
bool IsEmpty();
};
typedef Node* Tree;
Tree ConstructDecisionTree(int lines);
double ComputeValue(Tree tr, set<string> s);
void DestroyTree(Tree tr);
int main() {
freopen("../A-large-practice.in", "r", stdin);
//freopen("../A-small-practice.in", "r", stdin);
//freopen("Input.txt", "r", stdin);
freopen("output.txt", "w", stdout);
int casenum;
int tline, anims;
string s;
cin>>casenum;
for(int p = 0; p < casenum; p++) {
cin>>tline;
Tree tr = ConstructDecisionTree(tline); //建树的过程应该是调试好了。
cout<<"Case #"<<(p + 1)<<":"<<endl;
cin>>anims;
cin.get();
for(int i = 0; i < anims; i++) {
int temp;
set<string>sets;
cin>>s>>temp; //Animal name and feature num
//getline(cin, s);
for(int i = 0; i < temp; i++) {
cin>>s;
sets.insert(s);
}
double ret = ComputeValue(tr, sets);
//cout<<setprecision(7)<<ret<<endl;
printf("%.7f\n", ret);
}
DestroyTree(tr);
}
}
Tree ConstructDecisionTree(int lines) {
Node *curNode, *root;
double weight;
char temp;
string feature;
Stack s;
for(int i = 0; i < lines; i++) {
do {
cin>>temp;
}while(temp != LEFTBRACKET && temp != RIGHTBRACKET); //May cause infinite loop
if(temp == RIGHTBRACKET) {s.Pop(); continue;}
//We encouter a leftbracket
cin>>weight; //we get the weight
cin>>feature; //Try to get the feature
cin.get();
curNode = new Node();
if(s.IsEmpty()){
root = curNode;
}else {
if(s.Top()->left == 0) s.Top()->left = curNode;
else s.Top()->right = curNode;
}
s.Push(curNode);
//if feature contains too many ")"
if(feature[0] != RIGHTBRACKET) {
curNode->set(weight, false, feature);
}else {
//there are feature.size() ‘)’
for(int k = 0; k < feature.size(); k++) s.Pop();
curNode->set(weight);
}
}
return root;
}
double ComputeValue(Tree tr, set<string> s) {
//s中查找字符串
double pro = 1.0f;
Node *p = tr;
//set<string>::iterator it;
while(true) {
pro *= p->weight;
if(p->leaf) break;
else {
/*
if(s.find(p->feature) != string::npos) p = p->left;
else p = p->right;
假设为s为 sdd, ddd, sdsdfd,
那么当p->feature为dd时候,会显示为正确
要考虑越界的情形,还有其他的问题。 果然是这个问题
*/
if(s.find(p->feature) != s.end() ) p = p->left;
else p = p->right;
}
}
return pro;
}
void DestroyTree(Tree tr) {
if(tr == 0) return;
DestroyTree(tr->right);
DestroyTree(tr->left);
delete tr;
}
//字符串处理方面太弱了,一定得补上
void Node::set(double w, bool l, string fe){
weight = w;
leaf = l;
feature = fe;
}
void Node::set(double w) {
weight = w;
}
void Stack::Push(Node * v) {
a[++top] = v;
}
void Stack::Pop() {
--top;
}
Node* Stack::Top() {
return a[top];
}
bool Stack::IsEmpty() {
return top == -1;
}
总结:
感觉自己还是不大懂得用C++,事实上使用Python做文本处理是更好的选择。 决定最近去掌握一下Python和Lisp。