OJ系列-UVA232(Crossword Answers)java版

签到,今天是连续OJ系列的12天。
Crossword Answers, ACM/ICPC World Finals 1994,又是一道决赛题,在没有经过任何查找网上的代码的情况下,自己写出了这两道决赛题(OJ系列第11天),并且AC,还是小有成就感的。

题目

输入一个r行c列( 1≤r, c≤10) 的网格, 黑格用“*”表示, 每个白格都填有一个字母。 如果一个白格的左边相邻位置或者上边相邻位置没有白格( 可能是黑格, 也可能出了网格边界) , 则称这个白格是一个起始格。首先把所有起始格按照从上到下、 从左到右的顺序编号为1, 2, 3,…, 如图所示
在这里插入图片描述接下来要找出所有横向单词( Across) 。 这些单词必须从一个起始格开始, 向右延伸到一个黑格的左边或者整个网格的最右列。 最后找出所有竖向单词( Down) 。 这些单词必须从一个起始格开始, 向下延伸到一个黑格的上边或者整个网格的最下行。

样例输入

2 2
AT
*O
6 7
AIM*DEN
*ME*ONE
UPON*TO
SO*ERIN
*SA*OR*
IES*DEA
0

意思就是输入0结束程序

样例输出

puzzle #1:
Across
  1.AT
  3.O
Down
  1.A
  2.TO
  
puzzle #2:
Across
  1.AIM
  4.DEN
  7.ME
  8.ONE
  9.UPON
 11.TO
 12.SO
 13.ERIN
 15.SA
 17.OR
 18.IES
 19.DEA
Down
  1.A
  2.IMPOSE
  3.MEO
  4.DO
  5.ENTIRE
  6.NEON
  9.US
 10.NE
 14.ROD
 16.AS
 18.I
 20.A

可以看出,每个样例之间有个换行,然后输出的数字有3个宽度。

代码

import java.util.Scanner;
public class Main {

	/**
	 * @param args
	 */
	public static void main(String[] args) {
		// TODO Auto-generated method stub
		Scanner scanner=new Scanner(System.in);
		int r;
		int c;
		int kase=0;
		while(true){
		r=scanner.nextInt();
		if(r==0){//如果是0则程序退出
			return;
		}
		if(kase!=0){//控制输出换行,第一个样例不输出换行
			System.out.println();
		}
		c=scanner.nextInt();
		int count=1;//记录字母对应的数字
		char [][]matrix=new char[r][c];
		int [][]num=new int[r][c];//字母对应的数字数组
		for(int i=0;i<r;i++){
			String str=scanner.next();
			for(int j=0;j<c;j++){
				matrix[i][j]=str.charAt(j);
			}
			
		}
		for(int i=0;i<r;i++){//遍历找起始格,并且将 数字记录在数字数组
			for(int j=0;j<c;j++){
				if((matrix[i][j]!='*')&&(i==0||j==0||(matrix[i-1][j]=='*'||matrix[i][j-1]=='*'))){
					num[i][j]= count;
					count++;
				}
				
				
			}
		}
		
		for(int i=0;i<r;i++){//遍历找黑格,并在数字数组做好标记,之所以不在上一个循环中做,会影响找起始格
			for(int j=0;j<c;j++){
				if(matrix[i][j]=='*'){
					num[i][j]=-1;
				}
			}
		}
		//得到Across单词
		System.out.printf("puzzle #%d:\n",(++kase));
		System.out.println("Across");
		for(int i=0;i<r;i++){
			String s="";
			int cout=0;//用于找到最开始的起始格
			for(int j=0;j<c;j++){
				if(num[i][j]!=-1){//如果不是黑格子
					s+=matrix[i][j];//将单个字母拼接在一起
					cout++;
				}else{//遇到黑格子
					if(s!=""){
						
					System.out.printf("%3d%s\n",num[i][j-cout],"."+s);//格式化输出
					}
					s="";//置空,以便下次记录
					cout=0;
				}
				if(j==c-1&&(s!="")){//到一行的末尾,并且当前的单词不为空,就输出该单词
					System.out.printf("%3d%s\n",num[i][j-cout+1],"."+s);
				}
			}
		}
		//得到Down单词,不过先存到一个字符串数组中,方便根据序号从小到大输出
		//与找Across单词不同的是:一列一列的读,找到Down单词,连同最初的起始格的数字储存起来,其他原理同找Across
		String []ch=new String[count];
		for(int j=0;j<c;j++){//列
			String s1="";
			int cout1=0;
			for(int i=0;i<r;i++){//行
				if(num[i][j]!=-1){
					s1+=matrix[i][j];
					cout1++;
				}else{
					if(s1!=""){
					ch[num[i-cout1][j]]=s1;
					}
					s1="";
					cout1=0;
				}
				if(i==r-1&&(s1!="")){
					ch[num[i-cout1+1][j]]=s1;
				}
			}
		}
		//输出所有的Down单词,过滤掉没有储存的
		System.out.println("Down");
		for(int i=0;i<ch.length;i++){
			if(ch[i]!=null){
				System.out.printf("%3d%s\n",i,"."+ch[i]);
				
			}
		}
		}
		
	}

}

意料之中又报了演示错误,不过这次的原因很清楚,就是最后多输出一行,结果还报演示错误,仔细看了看,原来宽度是3个,我看成了2个,改掉,成功AC,此次还不算煎熬的就解决了。

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值