Homework-04

一、问题描述

本次作业的题目要求利用给定的一组单词生成一个矩阵,矩阵的每个位置由一个字母填充,单词表中的每一个单词可以匹配矩阵中一段连续的序列,这段序列可以是横向,纵向或者是45度斜角方向,单词可以由左向右匹配,也可以逆向匹配。题目将生成的矩阵分为3个等级,任意一个等级要求满足前一级所有要求。第一级要求每个方向上至少出现两个单词,总共四个方向,矩阵横纵规模可以不等,每个单词在矩阵中仅能被覆盖一次,不能存在一行或一列不被任何短语覆盖;第二级要求矩阵横纵相等;第三级要求四个角必须被覆盖。最后返回的矩阵期望能有尽可能小的规模。

二、问题分析

1. 每个单词在矩阵中出现,且只出现1次 2. 上下、下上、左右、右左及对角线共8个方向,每个方向均不少于2个单词排布。 3. 矩阵长宽可以不同 4. 不存在无效行或列 5. (进阶要求)矩阵为正方形 6. (进阶要求)矩阵四角有单词覆盖

 

我们讨论出的解题思路是枚举+暴力搜索。再进行一部分优化。

 

三、解题思路

我们的思想是直接做矩阵为正方形的这种情况。因为之前又一次上课我们已经讨论过这道题。

我们的思路是

1.首先把所有的单词按长度由大到小排列

2.8个不同方向我们分别用向量 水平左(-1,0),斜左上(-1,1),竖直上(0,1),斜右上(1,1),水平右(1,0),斜右下(1,-1),竖直下(0,-1),斜左下(-1,-1),

3.然后从字符长度最长的单词开始往里加入。每一次加入时给该单词的第一个位置随机生成一个(x,y),还有一个单词的方向 direct,随机生成很多次,然后就是计算这里得分最高的一组,在result—array的(x,y)处放置该单词的第一个字母,然后按照放置方向direct将该单词全部放入。

4、那么我们的分数是怎么计算的呢,我们的思路是这样的,如果放置的位置已经有了要放置的字母,那么这么放该字母的效率就非常高,所以就加一分。

 

 

四、源代码

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#define N 20
#define maxtry 100000
int totalnum=0;
char phrase_array[100][100];
char result_array[100][100];
int DX[8]={-1,-1,0,1,1,1,0,-1};
int DY[8]={0,1,1,1,0,-1,-1,-1};
void sort()
{
	int i,j;
	char s[100];
	 for(i=1;i<=totalnum;i++)
          for(j=i+1;j<=totalnum;j++)
                if(strlen(phrase_array[i])<strlen(phrase_array[j])){
                	strcpy(s,phrase_array[i]);
                	strcpy(phrase_array[i],phrase_array[j]);
                	strcpy(phrase_array[j],s);
                }                            
}
void input(FILE **p)
{
	int i=0,j;
	while(fscanf(*p,"%s",phrase_array[++totalnum])!=-1);
	totalnum--; 
	sort();	
 	for(i=1;i<=N;i++)
		for(j=1;j<=N;j++)
			result_array[i][j]=' ';
}
void insertword(char *phrase,int location_x,int location_y,int location_d)
{
	int i;
	for(i=0;i<strlen(phrase);i++)
	{
		result_array[location_x][location_y]=phrase[i];
		location_x+=DX[location_d];
		location_y+=DY[location_d];
	}
}
int calculate(char *phrase,int x,int y,int d)
{
	int i,score=0;
	for(i=0;i<strlen(phrase);i++)
	{	
		if(x>N||x<1||y>N||y<1)
			return -1;
		else if(phrase[i]==result_array[x][y])
			score++;
		else if(result_array[x][y]!=' ')
			return -1;
		x+=DX[d];
		y+=DY[d];
	}
}
int locateofrand(char *phrase,int *location_x,int *location_y,int *location_d)
{
	int best=-1;
	int i,x,y,d,temp;
	for(i=1;i<=maxtry;i++)
	{
		x=rand()%N+1;
		y=rand()%N+1;
		d=rand()%8;
		temp=calculate(phrase,x,y,d);
		if(temp>best)
		{
			best=temp;
			*location_x=x;
			*location_y=y;
			*location_d=d;
		}
	}
	return best;
}
void workprocess()
{
	int location_x,location_y,location_d,i,j,judge;
 	srand((int)time(0));
  	for(i=1;i<=totalnum;i++){
  		judge=locateofrand(phrase_array[i],&location_x,&location_y,&location_d);
    	if(judge==-1){
			printf("please change the value of N!\n");
		}
  		insertword(phrase_array[i],location_x,location_y,location_d);
    }
}
void output(FILE **p)
{
	int i,j;
	for(i=1;i<=N;i++){
 		for(j=1;j<=N;j++)
   			fprintf(*p,"%c",result_array[i][j]);
      	fprintf(*p,"\n");
   }
}
int main(int argc, char *argv[])
{
	FILE *in,*out;
	in=fopen("input.txt","r");
	out=fopen("result.txt","w");
	input(&in);
	workprocess();
	output(&out);	
	return 0;
}

五、总结

在这次的编程过程中,我们相互促进,共同学习讨论算法,完善判断思路与分数计算条件,虽然最终得出的搜索算法远远不能说是完成所有的要求和效率最高,但是我们已然完成了题目的要求,即8方向,无重复,四角有单词,矩阵最小。与此同时,我们的团队效率也较上次大大提升,面对后续的作业,我们充满信心~!

 

六、报告

Personal Software Process Stages

时间百分比(%)

实际花费的时间 (分钟)

原来估计的时间 (分钟)

计划

 10%  180  120

·         估计这个任务需要多少时间,把工作细化并大致排序

 10%  180  120

开发

 85%  1530  1020

·         需求分析 (包括学习新技术)

 15%  270  180

·         设计复审 (和同事审核设计文档)

 10%  180  120

·         代码规范 (制定合适的规范)

 5%  90  60

·         具体设计

 10%  180  120

·         具体编码

 35%  630  420

·         代码复审

 5%  90 60 

·         测试(自我测试,修改代码,提交修改)

 5%  90 60

总结报告

 5%  90  60
总计 100% 总用时  1800     总估计的用时 1200
 
posted @ 2013-10-29 15:27  elendir  阅读(197)  评论(0编辑  收藏  举报