exercise2 ACM文档格式.docx
《exercise2 ACM文档格式.docx》由会员分享,可在线阅读,更多相关《exercise2 ACM文档格式.docx(15页珍藏版)》请在冰豆网上搜索。
Begin[a1]<
End[a1]<
=…<
=Begin[an]<
End[an];
可以证明,如果在可能的事件a1<
an中选取在时间上不重叠的最长序列,那么一定存在一个包含a1(结束最早)的最长序列(序列长度是指事件个数而不是时间长度!
!
)。
示例中结束最早的事件是13,所以该事件就作为贪心算法中的初始解。
因为目标是使时间序列中的事件尽可能多,所以每一步贪心算法都是将不重叠的结束最早的事件加入时间序列。
程序实现:
//1.时间序列问题
#defineMax100//事件个数上限
voidmain()
{
intNumber;
//事件个数Number
intBegin[Max];
//事件开始时刻//下标表示事件编号
intEnd[Max];
//事件结束时刻
intresult[Max];
//存储最长的时间序列
intr=0;
//存储result[]的下标
cin>
>
Number;
//判断事件个数是否超出上限
if(Number>
Max)
{
cout<
<
"
事件个数超出上限!
endl;
exit
(1);
}
//输入时间序列
for(intj=0;
j<
j++)
cin>
Begin[j]>
End[j];
//寻找最长的时间序列
//首先将第一个最早结束的事件加入最长时间序列
result[0]=0;
//继续循环遍历所有事件构造最长时间序列
for(inti=1;
i<
i++)
if(Begin[i]>
=End[result[r]])
result[++r]=i;
//输出最长时间序列编号
for(intk=0;
k<
=r;
k++)
result[k]<
'
\t'
;
cout<
}
区间覆盖问题:
2、用i来表示x轴上坐标为[i-1,i]的区间(长度为1),并给出M(1=<
M=<
200)个不同的整数,表示M个这样的区间。
现在让你画几条线段覆盖住所有的区间,条件是:
每条线段可以任意长,但是要求所画线段之和最小,并且线段的数目不超过N(1=<
N=<
50)。
例如:
M=5个整数1、3、4、8和11表示区间,要求所用线段不超过N=4条
1234567891011
第一行为一个整数K,表示区间编号的最大数,当K=0时,程序结束,第二行为两个整数M和N,M表示需要覆盖的区间个数,N表示最大线段的数目,第三行包括M个正整数(不大于K),表示k个需要覆盖的区间编号。
在给定条件下所画线段之和的最小值。
11
54
134811
5
方法一:
(传统的一般解法)
先用一条最长的线段把整个区间覆盖起来,然后把区间点之间的空隔线段按照先长后短的顺序一一去掉,也就是贪心地使总线段长度尽可能短,知道线段的数量增加到到规定的数目停止;
方法二:
(个人原创想到的思路)
其实思想与方法一一样,只不过这里逆向思考不是先用一条最长的线段把整个区间覆盖,二是用最短的线段把所有的区间点覆盖,也就是每个区间点用一条单位长度的线段覆盖,那么有n个区间点,就需要总长度为n的线段,然后把每个小线段一一连接起来,还是贪心地线连接距离最短的,尽量使总长度最短,直到线段数量减少到规定数目停止。
//2.区间覆盖问题
//方法一
//降序排列函数指定,sort库函数默认是升序的
intdescend(inta,intb)
returna>
b;
intmain()
intn,m,minLength,max;
//区间点的个数n和所需的线段数m,覆盖线段的最短总长度minLength,区间点编号的最大数max
intpoint[200],distance[200];
//区间点数组point与区间点之间的距离数组distance
while(cin>
n>
m)//用户输入区间点的个数n和所需的线段数m
max;
//输入区间点编号的最大数,为0程序退出
if(!
max)
break;
for(inti=0;
n;
{
cin>
point[i];
}
sort(point,point+n);
//升序排列
minLength=point[n-1]-point[0]+1;
//全部覆盖的最长的一条线段的长度
for(i=0;
n-1;
distance[i]=point[i+1]-point[i]-1;
//将每两个区间点之间的距离存入distance数组
intnn=n-1;
//距离数组的实际长度
sort(distance,distance+nn,descend);
//将区间距离数组降序排列
m-1;
minLength-=distance[i];
//将链接区间点之间的线段按先去长后去短的顺序一一去掉知道线段条数达到要求
minLength<
return0;
/*
//方法二
intpoint[200],distance[199];
minLength=n;
//每个区间点用一个单位的线段覆盖时的线段的总长度
sort(distance,distance+nn);
//将区间距离数组升序排列
n-m;
minLength+=distance[i];
//将每一段单位线段按照距离最近一一连接起来,直到线段数目达到要求
*/
胜者败者问题:
(ThegameofNim)
3、两名参与者交替从一堆石子中取出若干数目,其个数由参与者自已决定.但是要求参与者每次至少取出一个,至多取出一半,然后另一名参与者继续.拿到最后一个石子的参与者将输掉该游戏.
输入开始时石子的个数
如果先取者输,则输出“lose”,否则输出“win”
由题意分析得必败点为1,3,7,15......,也就是2^n-1,其中n>
0,其余的都是必胜点。
//3.取石子(TheGameofNim)
//判断是不是2的幂
boolisPowerOf2(intn)
intnumber=n;
while(number)
if(number==1)
returntrue;
if(number%2)
returnfalse;
number/=2;
returntrue;
//石子的初始数目
if(Number==0)
win!
if(isPowerOf2(Number+1))
lose!
else
【估计也不会考这个】
母函数:
4、GivensomeChineseCoins(threekinds--1,2,5),andtheirnumberisnum_1,num_2andnum_5respectively,pleaseoutputtheminimumvaluethatyoucannotpaywithgivencoins.
Input
Inputcontainsmultipletestcases.Eachtestcasecontains3positiveintegersnum_1,num_2andnum_5(0<
=num_i<
=1000).Atestcasecontaining000terminatestheinputandthistestcaseisnottobeprocessed.
Output
Outputtheminimumpositivevaluethatonecannotpaywithgivencoins,onelineforonecase.
题目大意为给你三种不同价值的硬币,分别为一、二、五,告诉你各自的数量,求由这些钱币所不能组成的最小财富这并不是连续的数值,所以在进行表达式的展开时,用的是数组,而不是小标i。
constintMAX=1000;
constinttype[3]={1,2,5};
boolans[MAX],tmp[MAX];
intcnt[3];
voidSearch(){
inti,j,k;
//全部初始化为0
memset(ans,0,sizeof(ans));
memset(tmp,0,sizeof(tmp));
for(i=0;
=cnt[0];
++i){
ans[i]=true;
for(i=1;
3;
for(j=0;
=MAX;
++j){
for(k=0;
=cnt[i]&
&
j+k*type[i]<
++k){
//tmp[j+k*type[i]]+=ans[j];
if(tmp[j+k*type[i]]||ans[j])tmp[j+k*type[i]]=true;
ans[j]=tmp[j];
tmp[j]=false;
intmain(){
intres=0;
cnt[0]>
cnt[1]>
cnt[2]){
if(cnt[0]==0&
cnt[1]==0&
cnt[2]==0)break;
Search();
for(inti=0;
if(!
ans[i]){
res=i;
break;
res<
}
5、写出完整的二分查找程序,要求:
(1)先将给定的数据利用快速排序进行排序(采用复杂度为nlg(n)的算法)。
(2)利用二分查找法判断给定的数据是否在数据集中。
快速排序算法:
对于包含n个数的输入数组来说,快速排序是一种最坏情况时间复杂度为O(n^2)的排序算法,他的平均性能非常好,期望时间复杂度为nlgn.
与归并排序一样,快速排序也使用了分治思想:
快速排序是找出一个元素(理论上可以随便找一个)作为基准(pivot),然后对数组进行分区操作,使基准左边元素的值都不大于基准值,基准右边的元素值都不小于基准值,如此作为基准的元素调整到排序后的正确位置。
递归快速排序,将其他n-1个元素也调整到排序后的正确位置。
最后每个元素都是在排序后的正确位置,排序完成。
所以快速排序算法的核心算法是分区操作,即如何调整基准的位置以及调整返回基准的最终位置以便分治递归。
//快速排序
voidquicksort(intv[],intleft,intright)
if(left<
right)
intkey=v[left];
intlow=left;
inthigh=right;
while(low<
high)
while(low<
high&
v[high]>
key)
{
high--;
}
v[low]=v[high];
v[low]<
low++;
v[high]=v[low];
v[low]=key;
quicksort(v,left,low-1);
quicksort(v,low+1,right);
intsearch(inta[],intsize,intp)//二分法查找
intleft=0,right=size-1,mid=(left+right)/2;
while(right>
left)
if(a[mid]==p)
returnp;
elseif(a[mid]>
p)
right=mid-1;
elseleft=mid+1;
mid=(left+right)/2;
return-1;
voidmain()//主函数
intx,p;
inta[18]={4,13,8,10,1,6,5,2,18,11,12,9,17,16,3,7,14,15};
Peaseinputthenumberyouwanttoresearch:
p;
排序前的数组:
18;
a[i]<
"
//b_up(a,18);
quicksort(a,0,17);
排序后的数组:
x=search(a,18,p);
if(x==-1)
Thenumbercannotbefound!
Thenumber:
x<
wasfound!
【一般不会考】
6、ProblemDescription
Youaregivenanumberofcase-sensitivestringsofalphabeticcharacters,findthelargeststringX,suchthateitherX,oritsinversecanbefoundasasubstringofanyofthegivenstrings.
Thefirstlineoftheinputfilecontainsasingleintegert(1<
=t<
=10),thenumberoftestcases,followedbytheinputdataforeachtestcase.Thefirstlineofeachtestcasecontainsasingleintegern(1<
=n<
=100),thenumberofgivenstrings,followedbynlines,eachrepresentingonestringofminimumlength1andmaximumlength100.Thereisnoextrawhitespacebeforeandafterastring.
Thereshouldbeonelinepertestcasecontainingthelengthofthelargeststringfound.
SampleInput
2//测试案例个数
3//第一个案例中字符串的个数
ABCD
BCDFF
BRCD
2//第二个案例中字符串的个数
rose
orchid
SampleOutput
2
题目意思是在给定的n个字符串中找到最长连续公共子串的长度(字串可逆),如School中的ool和loop中的loo.因此我们可以考虑从给定的n个字符串中找出最短的,以该字符串生成所有可能的子串,搜索其他的字符串中是否也存在这样的字串,若不存在,则考虑子串的逆置是否存在.当子串或其逆置在每一个字符串中都存在,则该子串的长度就是所要求的值。
子串的生成如果从最小,即“1”开始则需要考虑所有情况,因此我们可以从最短字符串的长度开始生成,提高效率。
//求最长公共子串
#defineFOR(i,n)for(i=0;
i++)//用宏定义一个小函数,封装for循环
intN[10];
charstr[110][110];
//存放全部字符串
charst[110];
//寻找最短字符串short
charrevs[110];
//字串的倒置strrev
charvs[110];
//比较
voidstrev(){
charsw[110];
inti,tot=0;
strcpy(sw,revs);
for(i=strlen(sw)-1;
i>
=0;
i--)
revs[tot++]=sw[i];
revs[tot]='
\0'
intFind(intp){
intlens=strlen(st),rlens=strlen(st),i,j;
boolflag;
while(lens){//从最长的开始找
=rlens-lens;
i++){
strncpy(vs,st+i,lens);
strncpy(revs,st+i,lens);
//第二个复制,用于下面的倒置
vs[lens]=revs[lens]='
//尾问处理
strev();
//没有参数,但每次调用的作用都是倒置revs
flag=true;
N[p];
j++){//比较全部字符串
strstr(str[j],revs)&
!
strstr(str[j],vs)){
flag=false;
}
if(flag)
returnlens;
lens--;
returnlens;
//可能一个也没有,返回0
//主函数
intcaseNumber,i,x=110;
caseNumber;
intt=caseNumber;
while(t--){
N[t];
x=110;
FOR(i,N[t]){
str[i];
if(strlen(str[i])<
x){//寻找最短的字符串
x=strlen(str[i]);
strcpy(st,str[i]);
FOR(i,caseNumber){cout<
Find(i)<