四川大学算法设计.docx

上传人:b****3 文档编号:5439747 上传时间:2022-12-16 格式:DOCX 页数:22 大小:96.05KB
下载 相关 举报
四川大学算法设计.docx_第1页
第1页 / 共22页
四川大学算法设计.docx_第2页
第2页 / 共22页
四川大学算法设计.docx_第3页
第3页 / 共22页
四川大学算法设计.docx_第4页
第4页 / 共22页
四川大学算法设计.docx_第5页
第5页 / 共22页
点击查看更多>>
下载资源
资源描述

四川大学算法设计.docx

《四川大学算法设计.docx》由会员分享,可在线阅读,更多相关《四川大学算法设计.docx(22页珍藏版)》请在冰豆网上搜索。

四川大学算法设计.docx

四川大学算法设计

《算法设计》课程报告

 

课序号:

学号:

104304XXXX

姓名:

XXX

任课教师:

陈瑜

评阅成绩:

评阅意见:

 

提交报告时间:

2012年6月4日

一、动态规划

1、问题描述

下图是个数字三角,请编写一个程序计算从顶部至底部某处一条路径,使得该路径所经过的数字总和最大。

7

38

810

2744

1.每一步可沿左斜线向下或右斜线向下走;

2.1<=三角形行数<=100

3.三角形中的数字为整数0,1,……,99。

4.如果有多种情况结果都最大,任意输出一种即可。

输入:

第一行一个整数N,代表三角形的行数。

接下来N行,描述了一个数字三角。

输出:

第一行一个整数,代表路径所经过底数字总和。

第二行N个数,代表所经过的数字。

2、算法分析

很裸的DP,一个点的最优选择只能从下面和斜下面产生,所可以从最下的一层反面推到,并且中间用二维数组进行0或者1标记表示选择的是那个,以便查询路径。

动态啊规划转移方程:

dp[i-1][j]=max(dp[i][j],dp[i][j+1]);

3、核心代码

#include

#include

#include

usingnamespacestd;

intnum[100][100];

intmid[100][100];

intmm[100][100];

intn;

voidslove()

{

inti,j;

memset(mid,0,sizeof(mid));

for(i=n-1;i>=0;i--)

for(j=0;j

{

if(num[i][j]

{mid[i-1][j]=j+1;

num[i-1][j]+=num[i][j+1];

}

else

{

mid[i-1][j]=j;

num[i-1][j]+=num[i][j];

}

}

cout<

j=0;

for(i=0;i

{

cout<

j=mid[i][j];

}

cout<

}

intmain()

{

inti;

intj;

while(scanf("%d",&n)==1)

{

memset(num,0,sizeof(num));

for(i=0;i

for(j=0;j<=i;j++)

{scanf("%d",num[i]+j);mm[i][j]=num[i][j];}

slove();

}

}

4、测试数据

5、算法复杂度分析

时间复杂度O(n)=n+(n-1)+…+1=n*(n-1)/2;即时间复杂度为O(n^2)

空间复杂度为T(n)=3*(n^2);

6、和其他算法比较

很裸的一个动态题目,效率一般,还可以在空间上加以优化,即储存路径的空间可以优化一下,省出一定的空间。

二、二分搜索

1.问题描述

1.1问题概述

LumberjackMirkoneedstochopdownMmetresofwood.Itisaneasyjobforhimsincehehasa

niftynewwoodcuttingmachinethatcantakedownforestslikewildfire.However,Mirkoisonly

allowedtocutasinglerowoftrees.

Mirko?

smachineworksasfollows:

MirkosetsaheightparameterH(inmetres),andthemachine

raisesagiantsawbladetothatheightandcutsoffalltreepartshigherthanH(ofcourse,

treesnothigherthanHmetersremainintact).Mirkothentakesthepartsthatwerecutoff.

Forexample,ifthetreerowcontainstreeswithheightsof20,15,10,and17metres,andMirko

raiseshissawbladeto15metres,theremainingtreeheightsaftercuttingwillbe15,15,10,

and15metres,respectively,whileMirkowilltake5metresoffthefirsttreeand2metresoff

thefourthtree(7metresofwoodintotal).

Mirkoisecologicallyminded,sohedoesn?

twanttocutoffmorewoodthannecessary.That?

swhy

hewantstosethissawbladeashighaspossible.HelpMirkofindthemaximumintegerheightof

thesawbladethatstillallowshimtocutoffatleastMmetresofwood.

1.2输入

Thefirstlineofinputcontainstwospace-separatedpositiveintegers,N(thenumberoftrees,

1≤N≤1000000)andM(Mirko?

srequiredwoodamount,1≤M≤2000000000).

ThesecondlineofinputcontainsNspace-separatedpositiveintegerslessthan1000000000,

theheightsofeachtree(inmetres).ThesumofallheightswillexceedM,thusMirkowillalways

beabletoobtaintherequiredamountofwood.

1.3输出

Thefirstandonlylineofoutputmustcontaintherequiredheightsetting.

1.4事例

SampleInput

47

20151017

520

442402646

SampleOutput

15

36

2.算法分析

对于砍树,一定从在一个唯一的最优解,,所以首先针对于树的高度做一个从小到大的排序,针对于最后的结果M肯定有(i=0,j=n;min(tess[i…j])<=M<=max(tree[i…j]))并且有(getSumTree(i)>getSumTree(M)>getSumTree(j)(i

3.核心代码

#include

#include

#include

#include

#include

#include

#include

#include

#include

#definein(x)scanf("%d",&x);

#defineout(x)printf("%d\n",x);

usingnamespacestd;

constintN=1000001;

inttrees[N];

intn,m;

inlineboolcmp(constint&a,constint&b)

{returna>b;}

inlinelonglonggetSum(intmid);

intmain()

{

intl,r;

intmid;

longlongsum;

while(scanf("%d%d",&n,&m)!

=EOF)

{

l=r=0;

for(inti=0;i

{

in(trees[i]);

r=max(r,trees[i]);

}

sort(trees,trees+n,cmp);

while(l<=r)

{

mid=(l+r)>>1;

sum=getSum(mid);

if(sum<(longlong)m)r=mid-1;

elseif(sum==(longlong)m)break;

elsel=mid+1;

}

out((r+l)/2);

}

}

inlinelonglonggetSum(intmid)

{

longlongsum=0;

for(inti=0;i

if(trees[i]>mid)

sum+=trees[i]-mid;

elsebreak;

}

returnsum;

}

4.测试数据

5.算法复杂度分析

时间复杂度O(n*logn)=n+(n-1);

空间复杂度为T(n)=(n);

6.和其他算法比较

标准的二分,时间效率一般,还可以通过其他算法进行时间与优化,但思路简单,容易使用。

三、贪心算法

1.问题描述

1.1问题概述

Oneday,Tpkeyhasnothingtodowhenheglancesatsomekidsplayinggamesongridarea.Saddenlyhegetsanidea,

inventinganewmazegame.Firsthedrawsabiggridareaconsistingofn*nsmallgrid.Thegridareahasacompeletlycenter.

Theplayerwillstandatthecenter,thenheorshewasgivenahandofdirectionalorder,indicadingthattheplayer

shouldjumptotheneighbouringgridsuccessivelyinthisordereddirection.Butsomeofthisorderisreplacedby"?

",

sothattheplayercanjumpatanydirection.Thewinerwillbetheonewhoistheclosesttothegridareaboundary

intheprocessofjumping.Thenakidisplayingthegame,buthestop,thenhegiveathoughttoguaranteehewill

bethewiner.Hefeelsoconfused,butheknowyouareagoodcoder.Heneedsyourhelp

1.2输入

Thefirstofinputisanintegert(0

foreachcasewillincludetwolnes,anumber(int)andastring(length<1000),

thenumber'smeansisthatTpkeywilldrawasquareareawhichhasn*nsmallsquare.

andthestringwillincludefiveletters"EWSN?

"whichstandsfor"EASTWESTSOUTHNORTHandUndetermined"

andthestringlengthatmost1000.

1.3输出

foreachcase,theoutputshouldcontainasinglerealnumber,onasingleline:

theminimumdistancefromthesquareborderwhenhejumpedbytheinstructions

1.4样例

15

?

?

?

?

?

2

15

EE?

WWW

4

29

WS?

W?

S?

W?

SES

6

2.算法分析

很裸的贪心问题,遇到?

号的时候,对应的四个方向都可以选择,所以在前一次的基础之上都进行加1;最终结果所有的“问号”肯定为四种方向中的一种方向(对于最优宁愿同向也不怨反向或者不影响),所以可得,边算边保存中间最大,则就为题目离中心最远的距离,即为最优解。

3.核心代码

#include

#include

#include

#include

#include

#definein(x)scanf("%d",&x);

#defineout(x)printf("%d\n",x);

usingnamespacestd;

constintN=1005;

charstr[N];

intmain()

{

intnn;

intt;

scanf("%d",&t);

for(inttt=0;tt

{

scanf("%d\n",&nn);

scanf("%s",str);

intsum=0;

inte(0);

ints(0);

intw(0);

intn(0);

nn/=2;

for(inti=0;i

{

switch(str[i])

{

case'W':

w++;e--;

break;

case'E':

e++;w--;

break;

case'N':

n++;s--;

break;

case'S':

s++;n--;

break;

case'?

':

s++;n++;w++;e++;

break;

}

sum=max(sum,max(max(e,w),max(n,s)));

if(sum>nn)

{sum=nn;break;}

}

printf("Case#%d:

%d\n",tt+1,nn-sum);

}

}

 

4.测试数据

5.算法复杂度分析

时间复杂度o(n)的算法无法优化。

空间复杂度为T(n);可以进行优化达到T

(1)的算法。

使用getchar来进行输入。

6.和其他算法比较

很裸的一个贪心,算是最高效的算法,在空间上可以优化一些,做到无长数组的变量。

 

四、回溯法

1.问题描述

在一个N*N的棋盘上放置N个皇后,且使得每两个之间不能互相攻击,也就是使得每两个不在同一行,同一列和同一斜角线上。

2.算法分析

对于N=1,问题的解很简单,而且我们很容易看出对于N=2和N=3来说,这个问题是无解的。

所让我们考虑4皇后问题并用回溯法对它求解。

因为每个皇后都必须分别占据—行,我们需要做的不过是为棋盘上的每个皇后分配一列。

我们从空棋盘开始,然后把皇后1放到它所在行的第一个可能位置上,也就是第一行第—列。

对于皇后2,在经过第一列和第二列的失败尝试之后,我们把它放在第一个可能的位置,就是格子〔2,3),位于第二行第二列的格子。

这被证明是一个死胡同,因为皇后:

将没有位置可放。

所以,该算法进行回溯,把皇后2放在下一个可能位置(2,4)上。

然后皇后3就可以放在(3,2),这被证明是另一个死胡同。

该算法然后就回溯到底,把皇后1移到(1,2)。

接着皇后2到(2,4),皇后3到(3,1),而皇后4到(4,3),这就是该问题的一个解。

通过以此类推的关系得出相应输入N的结果。

3.核心代码

#include

#include

#include

#include

usingnamespacestd;

#defineN4

intcol[N+1];

//输出结果

voidOutput()

{

for(inti=1;i<=N;i++)

{

printf("(%d,%d)\n",i,col[i]);

}

printf("\n");

}

//求解函数

voidQueen(inti,intn)

{

if(i>n)

Output();

else

{

for(intj=1;j<=n;++j)

{

intk=1;

col[i]=j;

while(k

{

if((col[k]-col[i])*(fabs(col[k]-col[i])-fabs(k-i))!

=0)

{

k++;

if(k==i)

Queen(i+1,n);

}

else

{

break;

}

}

}

}

}

intmain()

{

printf("theansweris:

\n");

for(inti=1;i<=N;i++)

{

col[1]=i;//设置第一行

Queen(2,N);

}

system("pause");

}

4.测试数据

N==4N==5

5.算法复杂度分析

在N较小的时候时间效率很高,N在较大的时候,对于棋盘的扫描很多,使用数组的存储与加法的运算时的空间与时间上的效率都是很低的。

6.和其他算法比较

通过使用回溯的算法在一定程度上避免了一下多余操作,但算法并不是最优的,在处理较大的N时候可以进行优化。

优化1:

程序中的所有数在计算机内存中都是以二进制的形式储存的,而位运算就是直接对整数在内存中的二进制位进行操作,所以速度快,效率高。

因此选择用位运算来改进运算速度;优化2:

改进思路,对于不同的皇后问题,使用不同的方法计算,如,对于除2、3、8、9、14、15、26、27、38、39之外的任意N值皇后,可以用分治法进行计算。

(但不适合对于结果的输出)

五、分支限界法

1、问题描述

在3*3的棋盘上有8个将牌,每一个将牌都刻有1-8数码中的某一个数码。

棋盘中留有一个空格,允许其周围的某一个将牌向空格移动,这样通过移动将牌就可以不断改变将牌的布局。

给定一种初始时的将牌布局或结构(称作初始状态)和一个目标的布局(称作目标状态),问如何移动将牌,实现从初始状态到目标状态的改变,给出合法步骤中最小的移动步数。

如下图所示

输入格式:

首先输入一个数字t(t>=1&&t<=10)为测试数据的总数,接下来是t组测试数据,每组测试数据均由6行,每行3个数字组成,前3行为初始状态,后3行为目标状态,空格由0表示,每组测试数据前面有一个空行。

输出格式:

给出可以使初始状态转换到目标状态的最小移动次数,如果转化不到打印出-1。

输入样例:

2

283

164

705

230

184

765

283

164

705

283

146

705

输出样例:

3

-1

2、算法分析

很裸的一个A*搜索,中间加启发函数进行限定使得效率有大大的提高.首先声明一个一个结构体node来储存程序处理中间的状态八宫格的状态以及处理到这一步的值等。

其中num表示的将八宫格状态转换成一个整数,a[]怎保存的是起每个格子的值,zero表示空格的位置,ti表示已经走的步数,per估计值的结果,表示到目标点逆序数之和,h表示已走步数与估计值的和,代表这启发函数,并用来作为排序限定的作用,避免无效的搜索。

本题主要用的基础算法是BFS作为搜索,将每一次的扩展判定有效性,将有效的结果加入到优先队列中去,优先队列通过其启发函数进行排序,将较优的状态放到队头,以便及早扫描,,并用两个map进行标记,表示一个已经扫描过,且无效的,另一个表示正在扫描中,作为一些扫描值的限定,当扫描值等于要求结果值时,则寻找成功。

3、核心代码

/*A*搜索....*/

#include

#include

#include

#include

#include

#include

#include

usingnamespacestd;

intten[10]={1,10,100,1000,10000,100000,1000000,10000000,100000000,1000000000};

intzt[][4]={{-1,-1,3,1},{-1,0,4,2},{-1,1,5,-1},{0,-1,6,4},{1,3,7,5},{2,4,8,-1},{3,-1,-1,7},{4,6,-1,8},{5,7,-1,-1}};

structnode;

structnode{

intnum;

inta[9];

intzero;

intti;

intpre;

inth;

voidsetPer(constnode&end)

{

pre=0;

for(inti=0;i<9;i++)

{if(a[i]==0)continue;

for(intj=0;j<9;j++)

{if(end.a[j]==a[i])

pre+=abs(i%3-j%3)+abs(i/3-j/3);

}

}

h=pre+ti;

}

voidsetNum()

{

num=0;

for(intj=0;j<9;j++)

{num+=ten[8-j]*a[j];

if(a[j]=

展开阅读全文
相关资源
猜你喜欢
相关搜索

当前位置:首页 > 求职职场 > 笔试

copyright@ 2008-2022 冰豆网网站版权所有

经营许可证编号:鄂ICP备2022015515号-1