homework-02

1.第一题的核心思想就是一个简单的动态规划,即a[i]+=a[i-1]>0?a[i-1]:0;

但是这样只算成功了一半,我们要做的不是一道题,而是一个普通人可以用的程序。

而要把它编译成可执行文件,就要考虑很多边界因素,比如

(1)输入了几个参数?在这道题中只允许输入一个参数,就是文件名;

(2)输入的是不是合法的文件名;

(3)文件里的数据是否正确;

(4)程序是否有能力处理文件中的数据。

因此,我在前面加了很多的逻辑判断。

之前老师说道了代码覆盖率的问题,可能一条正确的指令加一个正确的文件的代码覆盖率很小,但是防患于未然。

(之前我一直以为覆盖率是说代码的紧凑程度,所以这个代码有点紧凑。。。)

 1 #include<stdio.h>
 2 int FindMax(int a[],int column)
 3 {
 4     int max=-1<<31,i;
 5     max=a[0];
 6     for(i=1;i<column;i++){
 7         a[i]+=a[i-1]>0?a[i-1]:0;
 8         max=max>a[i]?max:a[i];}
 9     return max;
10 }
11 int main(int argc,char* argv[])
12 {
13     if(argc==1){
14         printf("请在maxsun.exe后输入文件名\n");return -1;}
15     else if(argc>2){
16         printf("请在maxsun.exe后输入文件名,此为1.0版本,不支持任何附加参数\n");return -1;}
17     else{
18         if(freopen(argv[1],"r",stdin)==NULL){
19             printf("文件不存在,请尝试输入文件的完整路径\n");return -1;}
20         int row,column,i=0,a[1000],maxsum;
21         if(scanf("%d",&row)!=1){
22             printf("文本格式错误,请参照示例输入测试文本(行错误)\n");return -1;}
23         getchar();getchar();
24         if(scanf("%d",&column)!=1){
25             printf("文本格式错误,请参照示例输入测试文本(列错误)\n");return -1;}
26         getchar();
27         while(i<column){
28             getchar();
29             if(scanf("%d",&a[i++])!=1){
30                 printf("文本格式错误,请参照示例输入测试文本(数据与行列数不对应)\n");return -1;}
31             if(i>=1000){
32                 printf("数组越界,最多只能处理1000个数\n");return -1;}}
33         maxsum=FindMax(a,column);
34         printf("%d\n",maxsum);
35         fclose(stdin);}
36     return 0;
37 }

 

测试结果如下:

复杂度:O(n)

2.第二题跟第一题的区别就是变成了二维的,那我们只需要开一个一维的数组,枚举我们从文件中得到的二维数组的上下边界,然后将上下边界其中的元素都纵向相加,载入一位数组,这样问题就变回了第一题。

枚举上下界的时候最好一维数组中的临时数据可以重复使用,否则枚举上下界再压扁二维数组的复杂度就已经达到了O(M^3),接下来再找最大,复杂度就成了O(M^3*N)了。

 1 #include<stdio.h>
 2 #include<string.h>
 3 int FindMax(int a[],int column)
 4 {
 5     int max,i;
 6     int b[100];
 7     for(i=0;i<column;i++)
 8         b[i]=a[i];
 9     max=b[0];
10     for(i=1;i<column;i++)
11     {
12         b[i]+=(b[i-1]>0?b[i-1]:0);
13         if(max<b[i])
14             max=b[i];
15     }
16     return max;
17 }
18 int main(int argc,char* argv[])
19 {
20     if(argc==1)
21     {
22         printf("请在maxsun.exe后输入文件名\n");
23         return -1;
24     }
25     else if(argc>2)
26     {
27         printf("请在maxsun.exe后输入文件名,此为2.0版本,不支持任何附加参数\n");
28         return -1;
29     }
30     else
31     {
32         if(freopen(argv[1],"r",stdin)==NULL)
33         {
34             printf("文件不存在,请尝试输入文件的完整路径\n");
35             return -1;
36         }
37         int row,column;
38         if(scanf("%d",&row)!=1)
39         {
40             printf("文本格式错误,请参照示例输入测试文本(行错误)\n");
41             return -1;
42         }
43         if(row>100)
44         {
45             printf("行数超过限制,最多可允许100行\n");
46             return -1;
47         }
48         getchar();getchar();
49         if(scanf("%d",&column)!=1)
50         {
51             printf("文本格式错误,请参照示例输入测试文本(列错误)\n");
52             return -1;
53         }
54         if(column>100)
55         {
56             printf("列数超过限制,最多可允许100列\n");
57             return -1;
58         }
59         getchar();getchar();
60         int i,j;
61         int a[100][100];
62         memset(a,0,sizeof(a));
63         for(i=0;i<row;i++)
64             for(j=0;j<column;j++)
65             {
66                 if(scanf("%d",&a[i][j])!=1)
67                 {
68                     printf("文本格式错误,请参照示例输入测试文本(数据与行列数不对应)\n");
69                     return -1;
70                 }
71                 getchar();
72             }
73         int up,down;
74         int temp[100];
75         int record,maxsum=-1<<31;
76         for(up=0;up<row;up++)
77         {
78             memset(temp,0,sizeof(temp));
79             for(down=up;down<row;down++)
80             {
81                 for(j=0;j<column;j++)
82                     temp[j]+=a[down][j];
83                 record=FindMax(temp,column);
84                 if(record>maxsum)
85                     maxsum=record;
86             }
87         }
88         printf("%d\n",maxsum);
89         fclose(stdin);}
90     return 0;
91 }

每个大括号占一行!这样比第一题看起来爽多了有木有。。。

测试结果:

复杂度:O(M^2*N)

3.这个题太难了。以我的能力代码无法实现。

但是我想说说我对此题的看法。

(1)我首先想到的是回溯,但是之前的一维只要前面小于0就可以放弃,但是这个联通的话就无法压成一维,小于0也不能放弃。完全没有剪枝的条件。这样的无脑回溯我认为肯定是行不通的。

(2)第二个想法其实跟第一个想法差不多,这是回溯的时候先强力减一次枝,只要这个元素小于0就不要他,这样我们就得到了独立分散的若干个正数团。然后我们就可以找他们之间需要联通的最小代价,但是我发现找最小代价我也不会。

(3)第三个想法是一个二维的动态规划,因为我们在一维时用到的思想是以a[i]为终点(即a[i]以左)的最大子串,那把这个想法应用到二维,也去找以a[i][j]为终点的最大联通串,即a[i][j]以左以上的整个二维数组的最大联通串。

这个动态规划的方程应该是

a[i][j]=max(a[i-1][j-1]+...,a[i][j-1]+...,a[i-1][j]+...)

其中的...就是以a[][]为终点的最大联通区域的边界向右向下延伸一个单位所增加的数,并且这些数形成了之后的边界。

这个要用好多标记函数,无从下手。

(4)这个想法是我认为最接近正确解法的,就是我们先把每个横向的一维的数据都算出来,在每个a[i]中存放以他为终点的最大子串和以及起始位置,然后我们再纵向算一遍最大子串和,这样找到的最大子串可能就是要求的数了。

4.第四题跟第二题的区别就是加了个参数,在第二题的基础上,我们只需要识别出有效的参数,并对参数做出正确的反应即可。

  1 #include<stdio.h>
  2 #include<string.h>
  3 int flag=0;
  4 int maxsum=-1<<31;
  5 int a[100][100];
  6 int FindMax(int a[],int column)
  7 {
  8     int max,i;
  9     int b[100];
 10     for(i=0;i<column;i++)
 11         b[i]=a[i];
 12     max=b[0];
 13     for(i=1;i<column;i++)
 14     {
 15         b[i]+=(b[i-1]>0?b[i-1]:0);
 16         if(max<b[i])
 17             max=b[i];
 18     }
 19     return max;
 20 }
 21 void Find2DMax(int row,int column)
 22 {
 23         int up,down,j;
 24         int downBoundry=row;
 25         int temp[100];
 26         int record;
 27         for(up=0;up<row;up++)
 28         {
 29             memset(temp,0,sizeof(temp));
 30             if(flag==2)
 31                 downBoundry=up+row;
 32             for(down=up;down<downBoundry;down++)
 33             {
 34                 for(j=0;j<column;j++)
 35                     temp[j]+=a[down%row][j];
 36                 record=FindMax(temp,column);
 37                 if(record>maxsum)
 38                     maxsum=record;
 39             }
 40         }
 41 }
 42 
 43 int main(int argc,char* argv[])
 44 {
 45     if(argc==1)
 46     {
 47         printf("请在maxsun.exe后输入文件名\n");
 48         return -1;
 49     }
 50     else if(argc>3)
 51     {
 52         printf("此为3.0版本,仅支持一位参数:\n\t“/h”(水平相连)或“/v”(垂直相连)\n");
 53         return -1;
 54     }
 55     else
 56     {
 57         if(argc==3)
 58         {
 59             if(*argv[1]=='/'&&*(argv[1]+1)=='h')
 60                 flag=1;
 61             else if(*argv[1]=='/'&&*(argv[1]+1)=='v')
 62                 flag=2;
 63             else{
 64                 printf("无效的参数\n");
 65                 return -1;
 66             }
 67         }
 68         if(freopen(argv[argc-1],"r",stdin)==NULL)
 69         {
 70             printf("文件不存在,请尝试输入文件的完整路径\n");
 71             return -1;
 72         }
 73         int row,column;
 74         if(scanf("%d",&row)!=1)
 75         {
 76             printf("文本格式错误,请参照示例输入测试文本(行错误)\n");
 77             return -1;
 78         }
 79         if(row>100)
 80         {
 81             printf("行数超过限制,最多可允许100行\n");
 82             return -1;
 83         }
 84         getchar();getchar();
 85         if(scanf("%d",&column)!=1)
 86         {
 87             printf("文本格式错误,请参照示例输入测试文本(列错误)\n");
 88             return -1;
 89         }
 90         if(column>100)
 91         {
 92             printf("列数超过限制,最多可允许100列\n");
 93             return -1;
 94         }
 95         getchar();getchar();
 96         int i,j;
 97         memset(a,0,sizeof(a));
 98         for(i=0;i<row;i++)
 99             for(j=0;j<column;j++)
100             {
101                 if(scanf("%d",&a[i][j])!=1)
102                 {
103                     printf("文本格式错误,请参照示例输入测试文本(数据与行列数不对应)\n");
104                     return -1;
105                 }
106                 getchar();
107             }
108         Find2DMax(row,column);
109         printf("%d\n",maxsum);
110         fclose(stdin);
111     }
112     return 0;
113 }

在这里我把Find2DMax(找二维最大)也从main函数里分离了出来。

之前不想分离出来时因为二维数据传递很麻烦,要不就是指针,要不就是自定义结构体,要不就是全局变量。

我选择用全局变量,后来索性就多用了几个全局变量,比如参数的标志位,最大和。

从代码中可以看到其实要改的只要3个部分:

(1)逻辑判定中判定出/h和/v,并且把文件名位置改成argv[i-1];

(2)在Find2DMax中写出/v情况的分支做法;

(3)在FindMax中写出/h情况的分支做法;

第一个很简单,不再赘述;第二个就是在枚举上下界的时候,让下界可以循环到上界的前一个就可以了。

第三个我暂时还没想出来,不过可以确定只需要在最底层的FindMax中改动;

测试结果:

由于没有完全实现功能,所以我也不敢对复杂度下定论。

5.第五题与第四题基本上是没有区别的。

只需要改一下逻辑判断就可以了。因为在第四题的论述中,我们发现/h和/v是互不影响的,他们改动的就不是一个函数。 

 

 

  这次的作业令我获益匪浅:

(1)首先我学会了做软件或者程序的方法,那就是先做一个基本的功能,然后再慢慢地往上积累,循序渐进地开发,站在之前的基础上看世界,就能看得更高更远;

(2)切莫眼高手低,从12点做到现在已经5个多小时了,意思都模糊了。。以后有作业一定要早早开始做,不要想着临到时间了很快就会做完,看过之后才发现难度好大。

转载于:https://www.cnblogs.com/zhuxiaole/p/3348229.html

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值