单词接龙:是指一组单词序列,任何两个相邻的单词满足前一个单词的尾字母和后一个单词的首字母相同。 接龙长度:接龙中所有单词长度之和。 如单词:tea, cat, dog, aid, fish 可以形成单词接龙:cat tea aid dog 其中cat为龙头,dog为龙尾 接龙包含的单词个数为4 接龙长度为12 规格说明:
功能说明: 定义 1、最少接龙:单词数量最少的接龙 2、最短接龙:长度最短的接龙 给定一套单词库,请根据指定的龙头和龙尾,实现以下功能: 1、计算最少接龙包含的单词个数 2、计算最短接龙的长度 示例: 单词库由ab,beeec,bd,dc,cb五个单词组成,以ab为龙头,cb为龙尾的接龙中: 最少接龙:ab beeec cb(含有3个单词) 最短接龙:ab bd dc cb(接龙长度为8)
功能:添加单词 输入:单词 输出:无
功能:获取最少接龙的单词个数 输入:head 龙头 tail 龙尾 输出:单词个数(如果不能形成接龙、指定龙头龙尾不存在、龙头龙尾相同等,返回-1)
功能:获取最短接龙的长度 输入:head 龙头 tail 龙尾 输出:接龙的长度(如果不能形成接龙、指定龙头龙尾不存在、龙头龙尾相同等,返回-1)
| |
知识点: | |
题目来源: | 内部整理 |
练习阶段: | 挑战 |
运行时间限制: | 10Sec |
内存限制: | 128MByte |
输入: |
添加的一组单词序列,一行字符串,每个单词以空格隔开,如ab beeec bd dc cb 获取最少接龙的单词个数和获取最短接龙的长度,一行字符串,包括2个单词,分别是龙头单词和龙尾单词,如ab cb |
输出: |
2个整数,获取最少接龙的单词个数和获取最短接龙的长度,一个空格隔开 |
样例输入: |
ab beeec bd dc cb ab cb |
样例输出: |
3 8 |
答案提示: |
|
import java.util.ArrayList;
import java.util.List;
import java.util.Scanner;
public class Main {
/**
* @param args
*/
public static String head ="";
public static String end ="";
public static List<String> result = new ArrayList();
public static void main(String[] args) {
// TODO Auto-generated method stub
Scanner scan = new Scanner(System.in);// 接收控制台输入的信息
String str = scan.nextLine();
String headend = scan.nextLine();
String[] myarr = headend.split(" ");
List<String> my = new ArrayList();
String[] arr = str.split(" ");
for(int i = 0;i<arr.length;i++)
{
my.add(arr[i]);
}
//============= 指定龙头龙尾不存在
int flag=0;
for(int i=0;i<my.size();i++)
{
for(int j=0;j<myarr.length;j++)
{
if(my.get(i).equals(myarr[j]))
flag++;
}
}
if(flag!=2)
{
System.out.println(-1+" "+-1);
System.exit(0);
}
//=============龙头龙尾相同等
if(myarr[0].equals(myarr[1]))
{
System.out.println(-1+" "+-1);
System.exit(0);
}
//qudiao去掉 list中 龙头龙尾
for(int i=0;i<my.size();i++)
{
for(int j=0;j<myarr.length;j++)
{
if(my.get(i).equals(myarr[j]))
my.remove(i);
}
}
// System.out.println(my.toString());// 参与接龙的单词
// System.out.println(myarr[0]+myarr[1]);//龙头,龙尾
head=myarr[0];
end = myarr[1];
jielong(0,my);
int min=Integer.MAX_VALUE;
for(int i = 0;i<result.size();i++)//单词个数
{
String[] resultarr = result.get(i).split(",");
if(resultarr.length<min)
min = resultarr.length;
}
int minlength=Integer.MAX_VALUE;
for(int i = 0;i<result.size();i++)//最短接龙长度
{
String temp=result.get(i).replace(",", "");
if(temp.length()<minlength)
minlength = temp.length();
}
if(min==Integer.MAX_VALUE&&minlength==Integer.MAX_VALUE)
{
if(iscontinue(head,end))
{
System.out.println(2+" "+(head.length()+end.length()));
}
else
{
System.out.println(-1+" "+-1);
}
}
else
{
if(iscontinue(head,end))
{
System.out.println(2+" "+(head.length()+end.length()));
}
else
System.out.println(min+" "+minlength);
}
}
public static void jielong(int i,List<String> my)
{
for(int j=0;j<my.size();j++)
{
if(iscontinue(head,my.get(j)))
{
String temphead = head;
head=head+","+my.get(j);
String temp = my.get(j);
my.remove(j);
if(!iscontinue(head,end))
jielong(i+1,my);
else
{
// System.out.println(head+","+end);
result.add(head+","+end);
}
head=temphead;
my.add(i, temp);
}
}
}
public static boolean iscontinue(String begin,String end)
{
if(begin.charAt(begin.length()-1)==end.charAt(0))
return true;
else
return false;
}
}
主要用回溯法,和8皇后类似
开始有3个用例没有过,实在是检查不出来,每次只能提交一次真是坑爹,后来搜了下论坛上,看别人说错误要输出-1,-1;就改成这样了,不知道能不能通过
这是论坛上别人c++代码,貌似通过了,懒得试了
#include <iostream>
#include <string>
#include <sstream>
#include <vector>
#include <cmath>
#include <algorithm>
using namespace std;
void Find_Shortest_Path(int v,int *dist,bool len_or_count);
typedef struct Node
{
string word; //存储单词
struct Node *next;
int index; //存储该节点在容器中索引,图中每一个节点有一个唯一的索引值,一个节点的邻接节点构成单链表中节点的index值就是对应的
}NODE; //指针数组中(或说图中)的索引为index的节点,单链表中的节点其实是图中节点的副本,索引(编号)一样 ,都表示index这个节点
bool *flag_str; //存储某个节点是否被访问过的标志,这个标志必须单独,不能放到上面的节点中
vector<NODE *> nodvec; //头节点容器
int f_index,l_index; //存储龙头和龙尾在容器中的索引
int result_len=60000,result_count=60000; //查找的结果
int main()
{
string line,temp,first,last;
vector<string> vec;
int index=0;
getline(cin,line);
istringstream istr(line);
while(istr>>temp)
vec.push_back(temp);
sort(vec.begin(),vec.end());
vector<string>::iterator iter=unique(vec.begin(),vec.end());
vec.erase(iter,vec.end());
cin>>first>>last;
iter=vec.begin();
bool f_flag=false,l_flag=false;
while(iter!=vec.end()) //判断龙头和龙尾单词是否存在,是否相等
{
if(*iter==first)
{
f_flag=true;
f_index=iter-vec.begin();
}
if(*iter==last)
{
l_flag=true;
l_index=iter-vec.begin();
}
++iter;
}
if(first==last || !(f_flag && l_flag))
{
cout << -1 << " " << -1 << endl;
return -1;
}
iter=vec.begin();
flag_str=new bool[vec.size()](); //动态分配标志数组,标示某个节点是否已经加入到最短路径中
while(iter!=vec.end()) //将头节点的地址放到一个容器中
{
NODE *p=new NODE();
p->word=*iter;
p->next=NULL;
p->index=index++;
flag_str[p->index]=false;
nodvec.push_back(p);
++iter;
}
vector<NODE *>::iterator pfiter=nodvec.begin(),psiter=nodvec.begin();
while(pfiter!=nodvec.end()) //形成图
{
psiter=nodvec.begin();
while(psiter!=nodvec.end())
{
if((*pfiter)->word!=(*psiter)->word) //不要让自己是自己的后继
{
if((*psiter)->word[(*psiter)->word.length()-1]==(*pfiter)->word[0])
{
NODE *p=*psiter;
while(p->next!=NULL)
p=p->next;
NODE *q=new NODE();
q->index=(*pfiter)->index;
q->word=(*pfiter)->word;
q->next=NULL;
p->next=q;
}
}
++psiter ;
}
++pfiter;
}
int *dist=new int[nodvec.size()]();
Find_Shortest_Path(f_index,dist,false); //查找单词接龙所有路径中单词的最少个数
for(int i=0;i<vec.size();i++)
flag_str[i]=false;
Find_Shortest_Path(f_index,dist,true); //查找单词接龙所有路径中总单词的最小长度
for(int i=0;i<nodvec.size();i++) //释放内存
{
NODE *p,*q;
q=nodvec[i];
p=q->next;
delete q;
while(p!=NULL)
{
q=p;
p=p->next;
delete q;
}
}
delete [] flag_str;
delete [] dist;
if(result_len==60000 || result_count==60000)
{
cout << -1 << " " << -1 << endl;
return -1;
}
else
cout<<result_count<<" "<<result_len<<endl;
}
//查找路径中总单词长度最短的
//查找从源节点到其他所有顶点的最短路径的过程中,找到我的目标顶点就结束查找
void Find_Shortest_Path(int v,int *dist,bool len_or_count) //v是容器中的索引,实际对应一个节点,dist是动态分配的一个数组,元素个数是图节点的个数
{ //dist[i]存储源结点v到节点i的最短路径的长度
vector<NODE *>::iterator iter;
iter=nodvec.begin();
NODE *p=nodvec[v]->next;
//初始化路径长度(单词长度和单词个数)
while(p!=NULL) //初始化从头节点能直达的节点
{
if(len_or_count)
dist[p->index]=p->word.length();
else
dist[p->index]=1;
flag_str[p->index]=true; //标示为true的为已经初始化的节点,后面要重新置为false
p=p->next;
}
while(iter!=nodvec.end()) //初始化从头节点不能直达的节点
{
if((*iter)->index!=v) //自己的不搜索
{
if(flag_str[(*iter)->index])
flag_str[(*iter)->index]=false;
else
dist[(*iter)->index]=60000;
}
else //置自己的标志
flag_str[(*iter)->index]=true;
++iter;
}
for(int i=1;i<nodvec.size();i++) //总共要查找的次数为nodvec.size()-1次,当查找到目标节点,也直接结束
{
int minval=60000;
int vt=v;
for(int j=0;j<nodvec.size();j++)
{
if(!flag_str[nodvec[j]->index] && dist[j]<minval)
{
vt=j;
minval=dist[j];
}
}
flag_str[nodvec[vt]->index]=true;
p=nodvec[vt]->next;
while(p!=NULL)
{
if(!flag_str[p->index] && minval+p->word.length()<dist[p->index])
{
if(len_or_count)
dist[p->index]=minval+p->word.length();
else
dist[p->index]=minval+1;
}
p=p->next;
}
if(vt==l_index) //已经找到了目标了
{
if(len_or_count)
result_len=dist[vt]+nodvec[v]->word.length();
else
result_count=dist[vt]+1;
break;
}
}
}