解题报告.docx
《解题报告.docx》由会员分享,可在线阅读,更多相关《解题报告.docx(17页珍藏版)》请在冰豆网上搜索。
解题报告
ACM解题报告
班级:
191131
学号:
20131000806
姓名:
陈渊
日期:
2014年8月28日
题号:
1040
题目:
AsEasyAsA+B
类型:
排序算法
问题描述:
输入包含多次测试,每次测试给你一些整数(个数大于1,小于1000个),将它们按升序排列并输出
解题思路:
这是个排序算法题,排序算法有很多种,冒泡排序、直接插入排序、希尔排序。
。
。
。
。
。
还可以调用库函数达到目的。
此处使用希尔排序算法,并使用面向对象编程思想:
设计希尔排序类模板,具有intmaxsize;intlast;Tslist[size];三个属性包含希尔排序的成员函数。
核心希尔排序算法实现思想为:
线性表L长度为n时,取增量gap=n/2,即以L[0]和L[gap]为一组,L[1]和L[gap+1]为一组,L[2]和L[gap+2]为一组,……,L[n-gap]和L[n]为一组,分别进行插入排序。
再取gap=gap/2,则分组成为L[0],L[gap],L[2gap],……为一组,L[1],L[gap+1],L[2gap+1],……为一组,等等,分别进行插入排序。
直到gap=1,这时分组成为整个表,并只有一个组,再插入排序,完成全部任务。
程序流程图:
否
是
源代码:
*#include
#include
usingnamespacestd;
templateclassOrderedlist{
intmaxsize;
intlast;
Tslist[size];
voidShellinsert(constint);
public:
intgetlast(){returnlast;}
Tgetslist(intk){returnslist[k];}
voidputslist(Tt,intk){slist[k]=t;}
Orderedlist(){last=-1;maxsize=size;}
boolInsert(T&elem,inti);
voidprint();
voidShellsort();
};
templateboolOrderedlist:
:
Insert(T&elem,inti){
if(i<0||i>last+1||last==maxsize-1)returnfalse;
else{
for(intj=last;j>i;j--)slist[j]=slist[j-1];
slist[i]=elem;
last++;
returntrue;
}
}
templatevoidOrderedlist:
:
print(intn){
for(inti=0;i{
if(i==n-1)cout<elsecout<}
cout<}
templatevoidOrderedlist:
:
Shellsort(){//成员函数
intgap=(last+1)/2;
while(gap){
Shellinsert(gap);//一趟排序
gap/=2;
}
}
templatevoidOrderedlist:
:
Shellinsert(constintgap){
inti,j;
Ttemp;
//注意每一趟排序包含若干子序列,其中第一个子序列第一个元素是0号,第二个元素是gap号,
//插入排序认为单个元素是排好序的,所以从每个子序列的第二个元素开始插入排序。
for(i=gap;i<=last;i++)
{
//从第一个子序列开始直接插入排序,但不是完成一个子序列,
//再做下一个子系列,而是先做每个子序列的第一步,再做每个子序列的第二步,等等,
//穿插完成。
直接插入排序总是从后逐个向前,找到第一个比待插元素大的,则插在前面。
temp=slist[i];//待插元素放temp中
j=i;
while(j>=gap&&tempslist[j]=slist[j-gap];//找的元素,只要比temp大,就后移,空出位置
j-=gap;
}
slist[j]=temp;//将temp插入正确的空位
}
}
intmain()
{
intn=0;
intnum,j;
Orderedlistordlist;
cin>>j;
for(intk=0;k{
while(cin>>n&&n)
{
for(inti=0;i{
cin>>num;
ordlist.Insert(num,i);//建立顺序表
}
ordlist.Shellsort();//排序
ordlist.print(n);
}
}
return0;
}
题号:
1176
题目:
免费馅饼
类型:
动态规划
问题描述:
都说天上不会掉馅饼,但有一天gameboy正走在回家的小径上,忽然天上掉下大把大把的馅饼。
说来gameboy的人品实在是太好了,这馅饼别处都不掉,就掉落在他身旁的10米范围内。
馅饼如果掉在了地上当然就不能吃了,所以gameboy马上卸下身上的背包去接。
但由于小径两侧都不能站人,所以他只能在小径上接。
由于gameboy平时老呆在房间里玩游戏,虽然在游戏中是个身手敏捷的高手,但在现实中运动神经特别迟钝,每秒种只有在移动不超过一米的范围内接住坠落的馅饼。
现在给这条小径如图标上坐标:
为了使问题简化,假设在接下来的一段时间里,馅饼都掉落在0-10这11个位置。
开始时gameboy站在5这个位置,因此在第一秒,他只能接到4,5,6这三个位置中其中一个位置上的馅饼。
问gameboy最多可能接到多少个馅饼?
(假设他的背包可以容纳无穷多个馅饼)
输入数据有多组。
每组数据的第一行为以正整数n(0在结下来的n行中,每行有两个整数x,T(0同一秒钟在同一点上可能掉下多个馅饼。
n=0时输入结束。
解题思路:
将将要掉落的馅饼信息(时间、节点)储存于二维数组,再通过比较第五节点相邻节点的大小选择,每次扫描都选择相邻节点的大者,相加到第五节点,扫描完成后,输出最终结果。
程序流程图:
是
否
源代码:
#include
usingnamespacestd;
inta[100005][11];
intmax(inta,intb)
{
if(a>b)returna;
elsereturnb;
}
intmain()//******天上掉下馅饼
{
intn,i,j,x,time,maxtime;
while(cin>>n&&n)
{
memset(a,0,sizeof(a));
maxtime=0;
for(i=0;i{
cin>>x>>time;
a[time][x]++;
if(time>maxtime)
maxtime=time;
}
for(i=maxtime-1;i>=0;i--){
for(j=0;j<=10;j++)
{
if(j==0)
a[i][j]+=max(a[i+1][j],a[i+1][j+1]);
elseif(j==10)
a[i][j]+=max(a[i+1][j-1],a[i+1][j]);
else
{
intmad=max(a[i+1][j-1],a[i+1][j]);
a[i][j]+=max(mad,a[i+1][j+1]);
}
}
}
cout<}
return0;
}
题号:
1381
题目:
CrazySearch
类型:
Hash算法
问题描述:
输入包含多次测试,每次测试给你一个字符串(字符个数大于1,小于16000000个)及子串包含字符的个数,计算其中出现不同子串的个数并输出。
解题思路:
这是个Hash算法题,可以使用string对象存储字符串,获得字符串后进行子串分拆,并存储在vector容器内,使用标准库函数将vector容器元素其排序(也可以自己写排序函数),再调用标准库函数unique(arr.begin(),arr.end());使其元素唯一化。
输出容器内剩余元素个数即为所求。
程序流程图:
否
是
源代码:
#include
#include
#include
#include
#include
#include
#include
usingnamespacestd;
intmain()//******CrazySearch
{
intT,N,NC;
cin>>T;
while(T--)
{
stringtext;
cin>>N>>NC>>text;
vectorarr;
NC=1;
for(size_ti=0;i<=text.size()-N;++i)
{
stringtmp(text,i,N);//***从i后N个
if(NC)arr.push_back(tmp);
}
sort(arr.begin(),arr.end());//*****要先排序才能unique!
vector:
:
iteratorend_unique=unique(arr.begin(),arr.end());
arr.erase(end_unique,arr.end());
cout<}
return0;
}
题号:
1564
题目:
playagame
类型:
博弈论
问题描述:
每次测试输入一个整数n(1<=n<=10000,输入0结束测试),代表n*n格式的棋盘,一个棋子放在角落,每次棋手可以将棋子移动到相邻并且本局未曾移动到的格子里,最先无法动棋子的一方为输棋。
每局开始8600首先移动,ailyanlu后移动
请计算每局的赢家,并输出。
解题思路:
这道题赢家的关键就是最先抢夺过程中剩余可以走的个数为奇数的状态,总的个数为n*n刚开始可以走的个数为n*n-1,如果n为偶数n*n-1为奇数,则第一个走的人面临的就是必赢状态,否则第二走的人会赢。
相互贴着走就是
所以n为偶数时8600为赢家,否则ailyanlu为赢家。
程序流程图:
否
是
源代码:
#include
usingnamespacestd;
intmain()//******playagame
{
intn;
while(cin>>n)
{
if(n==0)
break;
if(n%2==0)
printf("8600\n");
else
printf("ailyanlu\n");
}
return0;
}
题号:
2037
题目:
今年暑假不AC
类型:
贪心算法
问题描述:
输入数据包含多个测试实例,每个测试实例的第一行只有一个整数n(n<=100),表示你喜欢看的节目的总数,然后是n行数据,每行包括两个数据Ti_s,Ti_e(1<=i<=n),分别表示第i个节目的开始和结束时间,为了简化问题,每个时间都用一个正整数表示。
n=0表示输入结束,不做处理。
求每次测试能看到的最多完整节目数目,并输出结果。
解题思路:
这是个贪心算法题,因为每个节目还包括开始时间和结束时间,所以使用2维数组n*2矩阵来保存时间数据,在保存数据的同时将节目按结束时间先后排序(提高时间效率),因为需要计算的是能看到完整节目的数目,这样排序方便选择可以看的完整节目。
统计可以看的完整节目时,必定是最先观看最早结束的节目(这样才是节约时间),这是第一个节目,第二个观看的是开始时间比第一个观看节目结束时间晚而且其结束时间在剩下的节目中又是最早结束的节目,第三个观看的是开始时间比第二个观看节目结束时间晚而且其结束时间在剩下的节目中又是最早结束的节目。
。
。
以此类推直至所有节目扫描完毕。
程序流程图:
否
是
源代码:
#include
#include
#include
#include
#include
#include
#include
#include
usingnamespacestd;
intmain()//******今年暑假不AC!
{
intarr[1005][2];
memset(arr,0,sizeof(arr));
intn;
while(cin>>n&&n)
{
for(inti=0;i{
cin>>arr[i][0]>>arr[i][1];
if(i>0)
{
intj=i;
inttmpe=arr[i][1];
inttmpb=arr[i][0];
while(j>0&&tmpe{
arr[j][0]=arr[j-1][0];
arr[j][1]=arr[j-1][1];
--j;
}
arr[j][1]=tmpe;
arr[j][0]=tmpb;
}
}
intsum=1;//****arr的第一个节目结束最早,必定有一;
intsym=0;//记录看完的节目的索引
for(inti=1;i{
if(arr[i][0]>=arr[sym][1])//这样就可以看第i个节目
{
sum++;
sym=i;
}
}
cout<}
return0;
}