题意:根据罗马数字与阿拉伯数的对应,在给定表格中,从左边走到右边(不能向左退),相邻格的走,到达右边后,求走过的罗马数字中的
合法串中的最小值。
解法:先通过预处理,建立Trie字典树,利用字典树判断路径串的合法性及其值大小。Trie数据结构+DFS算法。
注意:在DFS过程中,加入合法性判断进行剪枝,可提高效率。若得到整个串时才在Trie树中判断,则会超时。

源代码
#include<iostream>
#include<map>
#include<string>

using namespace std;

const int NLAT = 13;
const int MAXN = 17;
const int INF = 4000;


string lat[NLAT]=
{"M","CM","D","CD","C","XC","L","XL","X","IX","V","IV","I"};

int num[NLAT]=
{1000,900,500,400,100,90,50,40,10,9,5,4,1};

map<char,int> ch2Int;
char data[MAXN][MAXN];

//字典树节点结构
struct Node


{
int num;
Node *next[7];
};

Node *root; //字典树根节点
int n,m;


int dir[3][2] =
{
{-1,0},
{0,1},
{1,0}};
bool visited[MAXN][MAXN];

int minNum;
char ans[101]; //保存当前最优结果

//向字典树中添加新合法串
void Insert(string str, int num)


{
Node *p = root;

string::size_type i = 0;
string::size_type len = str.length();
for(string::size_type i = 0; i<len; i++)

{
int index = ch2Int[str[i]];
if(p->next[index] == NULL)

{
p->next[index] = new Node();
}
p = p->next[index];
}
p->num = num;
}

//构建Trie字典树
void BuildTrieTree()


{
ch2Int['I']=0;
ch2Int['V']=1;
ch2Int['X']=2;
ch2Int['L']=3;
ch2Int['C']=4;
ch2Int['D']=5;
ch2Int['M']=6;

root = new Node();

for(int i=1; i<INF; i++) //1-3999对应的罗马数字串

{
int t = i;
string str = "";
while(t)

{
int j; //此处可稍为优化,每次只从上一次点开始搜索
for(j=0; j<NLAT; j++)

{
if(t >= num[j])

{
break;
}
}
str = str.append(lat[j]);
t -= num[j];
}
Insert(str,i);
}
}

//DFS算法搜索罗马数字串
void DFS(char *res,int x,int y,int ind, Node *ptr)


{
if(y == m-1)

{
if(ptr->num < minNum)

{
minNum = ptr->num;
for(int i=0; i<ind; i++)

{
ans[i] = res[i];
}
ans[ind] = '\0';
}
return;
}

for(int i=0; i<3; i++)

{
int dx = x + dir[i][0];
int dy = y + dir[i][1];

if(dx>=0 && dx<n && dy<m && !visited[dx][dy] && ptr->next[ch2Int[data[dx][dy]]]!=NULL) //判断罗马串是否合法

{
visited[dx][dy] = true;
res[ind++] = data[dx][dy];

DFS(res,dx,dy,ind,ptr->next[ch2Int[data[dx][dy]]]);

visited[dx][dy] = false;
ind--;
}
}
}

//解函数
string Slove()


{
minNum = INF;
char res[101];

for(int i=0; i<n; i++)

{
for(int j=0; j<n; j++)

{
visited[i][j] = false;
}
}

for(int i=0; i<n; i++) //每行第一个顶点分别为出发顶点

{
visited[i][0] = true;
res[0] = data[i][0];

Node *p = root;
p = p->next[ch2Int[res[0]]];

DFS(res,i,0,1,p);

visited[i][0] = false;
}
if(minNum == INF)

{
return "NO";
}
else

{
return ans;
}
}

int main()


{
BuildTrieTree();
while(cin>>n>>m)

{
for(int i=0; i<n; i++)

{
cin>>data[i];
}
cout<<Slove()<<endl;
}
return 0;
}
