注:在输入数据的获取与处理上花了不少时间,因为每行的输入数据的个数不再确定,所以需要先读取一行,然后从该行字符串中解析出我们需要的数据。
一、工程代码及算法设计注释
--------------------------------------------------nta.h----------------------------------------------
#ifndef JLU_CCST_NTA_H
#define JLU_CCST_NTA_H
#include <vector>
struct SignalPair{
int x,y;
SignalPair(int xx=0,int yy=0):x(xx),y(yy) {} ;
};
struct TreeNode{
char transmiter;
TreeNode* left;
TreeNode* right;
TreeNode(char trans='a',TreeNode* l=NULL,TreeNode* r=NULL):transmiter(trans),left(l),right(r) {} ;
};
extern bool isNTATreeValid(const std::vector<std::vector<SignalPair> >& transitionTable,int signal,int n,int m,int k,TreeNode* root);
extern void testIsNTATreeValid();
#endif//JLU_CCST_NTA_H
-------------------------------------------------- nta.cpp ----------------------------------------------
/**
题目来源:浙大ACM在线测试——ZOJ,题目编号1011,题名"NTA"
URL:http://acm.zju.edu.cn/onlinejudge/showProblem.do?problemCode=1011
Author:hellogdc<gdcjlu@163.com>
Finish Time:2014.01.09
*/
/**
算法设计:
利用递归思想来解决该问题,即判断一棵树是否“shakable”,可转化为判断这颗树根节点的左子树和右子树
是否同时“shakable”。如果可以,则说明该树“shakable”;否则,则不可以。
关于树的表示:
用最传统的二叉树来表示,每个节点由3个元素组成:左儿子、右儿子和信号发射器。
*/
#include <iostream>
#include <vector>
#include "nta.h"
using namespace std;
/**
给定NTA,判断一棵树是否“shakable”。如是,则返回true;否则,返回false。
transitionTable:信号转发表,此处是用一个数组来模拟矩阵的,行坐标为信号值(从0开始),列坐标为信号发射器值(从a开始)。
sinal:该树根节点收到的信号(从0开始)。
n:NTA信号个数
m:NTA信号"acceptable"的个数
k:NTA信号发射器个数
root:要判断的树的根节点,另外这棵树的每个非叶子节点必须有2个子节点。
*/
bool isNTATreeValid(const vector<vector<SignalPair> >& transitionTable,int signal,int n,int m,int k,TreeNode* root){
if( (root->left==NULL&&root->right!=NULL)||
(root->left!=NULL&&root->right==NULL) )
return false;
int acceptMin=n-m;
vector<SignalPair> pairs=transitionTable.at(signal*k+root->transmiter-'a');
//处理叶子节点
if(root->left==NULL&&root->right==NULL){
//查表
for(vector<SignalPair>::iterator it=pairs.begin();it!=pairs.end();it++){
if(it->x>=acceptMin&&it->y>=acceptMin)
return true;
}
return false;
}
//处理非叶子节点
for(vector<SignalPair>::iterator it=pairs.begin();it!=pairs.end();it++){
if( isNTATreeValid(transitionTable,it->x,n,m,k,root->left) ){
if( isNTATreeValid(transitionTable,it->y,n,m,k,root->right) ){
return true;
}
}
}
return false;
}
static void freeTree(TreeNode* root){
if(root==NULL)
return;
freeTree(root->left);
freeTree(root->right);
delete root;
}
/Test Case/
void testIsNTATreeValid(){
vector<vector<SignalPair> > transitionTable;
int n,m,k;
transitionTable.clear();
n=4;m=2;k=3;
{
vector<SignalPair> pairs;
pairs.push_back(SignalPair(1,2));
transitionTable.push_back(pairs);
}
{
vector<SignalPair> pairs;
pairs.push_back(SignalPair(2,1));
transitionTable.push_back(pairs);
}
{
vector<SignalPair> pairs;
pairs.push_back(SignalPair(1,0));
transitionTable.push_back(pairs);
}
{
vector<SignalPair> pairs;
pairs.push_back(SignalPair(2,2));
transitionTable.push_back(pairs);
}
{
vector<SignalPair> pairs;
pairs.push_back(SignalPair(0,2));
pairs.push_back(SignalPair(1,0));
transitionTable.push_back(pairs);
}
{
vector<SignalPair> pairs;
pairs.push_back(SignalPair(3,2));
transitionTable.push_back(pairs);
}
{
vector<SignalPair> pairs;
pairs.push_back(SignalPair(2,2));
transitionTable.push_back(pairs);
}
{
vector<SignalPair> pairs;
pairs.push_back(SignalPair(2,3));
transitionTable.push_back(pairs);
}
{
vector<SignalPair> pairs;
pairs.push_back(SignalPair(1,2));
transitionTable.push_back(pairs);
}
{
vector<SignalPair> pairs;
pairs.push_back(SignalPair(1,2));
transitionTable.push_back(pairs);
}
{
vector<SignalPair> pairs;
pairs.push_back(SignalPair(2,1));
transitionTable.push_back(pairs);
}
{
vector<SignalPair> pairs;
pairs.push_back(SignalPair(3,2));
transitionTable.push_back(pairs);
}
TreeNode* root=new TreeNode('a');
root->left=new TreeNode('b');
root->right=new TreeNode('c');
root->left->left=new TreeNode('a');
root->left->right=new TreeNode('b');
root->right->left=new TreeNode('c');
root->right->right=new TreeNode('b');
root->left->left->left=new TreeNode('b');
root->left->left->right=new TreeNode('a');
root->left->right->left=new TreeNode('b');
root->left->right->right=new TreeNode('a');
root->right->left->left=new TreeNode('c');
root->right->left->right=new TreeNode('a');
TreeNode* root2=new TreeNode('b');
root2->left=new TreeNode('a');
root2->right=new TreeNode('b');
root2->left->left=new TreeNode('b');
root2->left->right=new TreeNode('c');
bool flag=false;
flag=isNTATreeValid(transitionTable,0,n,m,k,root);
if(flag)
cout<<"Valid"<<endl;
else
cout<<"Invalid"<<endl;
flag=isNTATreeValid(transitionTable,0,n,m,k,root2);
if(flag)
cout<<"Valid"<<endl;
else
cout<<"Invalid"<<endl;
freeTree(root);
freeTree(root2);
}
--------------------------------------------------main.cpp----------------------------------------------
#if 1
#include "nta.h"
int main(){
testIsNTATreeValid();
return 0;
}
#endif
二、 提交并被ZOJ成功接受的代码——算法核心代码
--------------------------------------------------submit_main.cpp----------------------------------------------
#include <iostream>
#include <vector>
#include <string>
#include <cmath>
#include <cstdlib>
using namespace std;
struct SignalPair{
int x,y;
SignalPair(int xx=0,int yy=0):x(xx),y(yy) {} ;
};
struct TreeNode{
char transmiter;
TreeNode* left;
TreeNode* right;
TreeNode(char trans='a',TreeNode* l=NULL,TreeNode* r=NULL):transmiter(trans),left(l),right(r) {} ;
};
bool IsNTATreeValid(const vector<vector<SignalPair> >& transitionTable,int signal,int n,int m,int k,TreeNode* root){
if( (root->left==NULL&&root->right!=NULL)||
(root->left!=NULL&&root->right==NULL) )
return false;
int acceptMin=n-m;
vector<SignalPair> pairs=transitionTable.at(signal*k+root->transmiter-'a');
if(root->left==NULL&&root->right==NULL){
for(vector<SignalPair>::iterator it=pairs.begin();it!=pairs.end();it++){
if(it->x>=acceptMin&&it->y>=acceptMin)
return true;
}
return false;
}
for(vector<SignalPair>::iterator it=pairs.begin();it!=pairs.end();it++){
if( IsNTATreeValid(transitionTable,it->x,n,m,k,root->left) ){
if( IsNTATreeValid(transitionTable,it->y,n,m,k,root->right) ){
return true;
}
}
}
return false;
}
static void freeTree(TreeNode* root){
if(root==NULL)
return;
freeTree(root->left);
freeTree(root->right);
delete root;
}
int main(){
vector<vector<vector<SignalPair> > > transitionTables;
vector<vector<TreeNode*> > trees;
vector<int> nS;
vector<int> mS;
vector<int> kS;
int n,m,k,level;
//because the max number of signal is 15, 15*15=225,225*2+224<800, so it's enough to store the input
char inBuf[800];
string line;
while(getline(cin,line)){
int start=0;
int end=line.find(" ",start);
string value=line.substr(start,end-start);
n=atoi(value.c_str());
start=end+1;
end=line.find(" ",start);
value=line.substr(start,end-start);
m=atoi(value.c_str());
start=end+1;
end=line.find(" ",start);
if(end==string::npos)
end=line.length();
value=line.substr(start,end-start);
k=atoi(value.c_str());
if(n==0&&m==0&&k==0)
break;
nS.push_back(n);
mS.push_back(m);
kS.push_back(k);
int tableSize=n*k;
vector<vector<SignalPair> > transitionTable(tableSize);
for(int i=0;i<tableSize;i++){
vector<SignalPair> paris;
//line=inBuf;
getline(cin,line);
int j=0;
int start=0,end=0;
while(start<line.length()){
SignalPair pair;
string value;
end=line.find(" ",start);
value=line.substr(start,end-start);
pair.x=atoi(value.c_str());
start=end+1;
end=line.find(" ",start);
if(end==string::npos)
end=line.length();
value=line.substr(start,end-start);
pair.y=atoi(value.c_str());
start=end+1;
paris.push_back(pair);
}
transitionTable[i]=paris;
}
transitionTables.push_back(transitionTable);
vector<TreeNode *> roots;
while(getline(cin,line)){
int start=0;
int end=line.find(" ",start);
if(end==string::npos)
end=line.length();
string value=line.substr(start,end-start);
level=atoi(value.c_str());
if(level==-1)
break;
vector<TreeNode*> nodes((int)pow(2.0,level+1)-1);
int no=0;
for(int i=0;i<=level;i++){
getline(cin,line);
for(int j=0;j<line.length();j+=2){
TreeNode* node=new TreeNode(line[j]);
nodes[no++]=node;
}
}
int nNonLeaf=(int)pow(2.0,level)-1;
for(int i=0;i<nNonLeaf;i++){
if(nodes[i]->transmiter=='*'){
delete nodes[i];
continue;
}
int sonI=2*i+1;
if(nodes[sonI]->transmiter!='*')
nodes[i]->left=nodes[sonI];
else{
nodes[i]->left=NULL;
delete nodes[sonI];
}
if(nodes[sonI+1]->transmiter!='*')
nodes[i]->right=nodes[sonI+1];
else{
nodes[i]->right=NULL;
delete nodes[sonI+1];
}
}
roots.push_back(nodes[0]);
}
trees.push_back(roots);
}
for(int i=0;i<trees.size();i++){
bool flag=false;
if(i!=0)
cout<<endl;
cout<<"NTA"<<(i+1)<<":"<<endl;
for(vector<TreeNode*>::iterator it=trees[i].begin();it!=trees[i].end();it++){
flag=IsNTATreeValid(transitionTables[i],0,nS[i],mS[i],kS[i],*it);
if(flag)
cout<<"Valid"<<endl;
else
cout<<"Invalid"<<endl;
}
}
for(int i=0;i<trees.size();i++){
for(vector<TreeNode*>::iterator it=trees[i].begin();it!=trees[i].end();it++){
freeTree(*it);
}
}
}