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 | 
                    
                
                
            
        
浙公网安备 33010602011771号