writeln(x); end;
close(input); close(output); end.
3.排队(queue.pas)
【问题描述】
按身高排队是我们最常用的一种排队方法,一伙小朋友已经非常厌倦了这种排队方式,这次他们打算按每个人的姓名排队,但如果按照姓名的字典序进行排队似乎有点麻烦,所以他们找了一种比较简单的排队方法:根据姓名的长度进行排队,姓名长的排在最前面,姓名短的排在最后面。
姓名的长度他们有这样的约定:每个人的姓名只能由“a”( ASCII码为97)到“z” (ASCII码为122)这26个小写英文字母构成,姓名的长度就是姓名中字母的总个数。 由于小朋友人数比较多,请根据他们的排队方法,编程帮助他们排队吧! 【输入数据】
输入文件queue.in:输入从文件中读取,输入共n+1行。 第1行是一个整数n(1≤n≤15000),表示总共有n个小朋友参加排队(编号为1到n)。 第2行到第n+1行,每行一个字符串,其中第i+1行表示第i 个小朋友的姓名,数据保证每个小朋友都有姓名,并且姓名的长度不超过255。 【输出数据】
输出文件queue.out:结果输出到文件中。
输出共n行,表示经过排队后的小朋友的姓名情况,姓名长的先输出,姓名短的后输出。注意,当小朋友的姓名长度一样时,输出的顺序同输入的顺序(参考样例解释)。 【输入输出样例】 queue.in 3
aoteman guaishou jiqiren queue.out guaishou aoteman jiqiren
【样例解释】
有3个小朋友参加了排队,第1个小朋友的姓名长度为7,第2个小朋友的姓名长度为8,第3个小朋友的姓名长度为7。因为第2个小朋友的姓名最长,所以最先输出,第1个小朋友和第3个小朋友的姓名长度都为7,但在输入中,小朋友“aoteman”在小朋友“jiqiren”的前面,所以先输出“aoteman”,然后输出“jiqiren”。 【数据范围约定】
60%的输入数据保证1≤n≤1000,且每个小朋友的姓名长度不超过100。 80%的输入数据保证1≤n≤8000,且每个小朋友的姓名长度不超过255。 100%的输入数据保证1≤n≤15000,且每个小朋友的姓名长度不超过255。 【问题分析】
给出一些字符串,按要求进行排序。
【算法分析】
排序,可采用双关键字快排。 【参考程序】 var n,i:longint;
a,b:array[1..15000] of longint; s:array[1..15000] of string;
procedure sort(l,r:longint); var i,j,t,mid,m:longint; begin
i:=l; j:=r; mid:=a[(i+j) div 2]; m:=b[(i+j) div 2]; repeat
while (a[i]>mid) or (a[i]=mid) and (b[i]
t:=a[i]; a[i]:=a[j]; a[j]:=t; t:=b[i]; b[i]:=b[j]; b[j]:=t; inc(i); dec(j); end; until i>j;
if l begin assign(input,'queue.in'); reset(input); assign(output,'queue.out'); rewrite(output); readln(n); for i:=1 to n do begin readln(s[i]); a[i]:=length(s[i]); b[i]:=i; end; sort(1,n); for i:=1 to n do writeln(s[b[i]]); close(input); close(output); end. 4.寻找子矩阵(matrix.pas) 【问题描述】 一个由n行m列构成的矩阵(从上到下对行1到n编号,从左到右对列1到m编号), 第i 行第j 列中有一个正整数Wij。例如下面是一个3行4列的矩阵。 现在从中选取一个p行q列的子矩阵,例如下面黑框中选取的是一个2行3列的子矩阵。 仔细观察会发现,从上面的矩阵中选取2行3列的子矩阵共有4种不同的方法。 现在请你找这样一个子矩阵,满足以下条件: 将子矩阵的q列从左到右编号为1到q,删除子矩阵中所有编号为奇数的列,或者删除子矩阵中所有编号为偶数的列,然后 用子矩阵中剩下的数之和 减掉 子矩阵中被删除的数之和,得到一个结果S,S最大的子矩阵就是我们要找的子矩阵,注意,这样的子矩阵可能有多个。 例如上面黑框中的子矩阵,删除编号为奇数的列(下图1)或删除编号为偶数的列(下图2)。(阴影部分为删除的列) 按照计算规则,图1中剩下的数之和为8,被删除的数之和为9,所以S=-1,图2中剩下的数之和为9,被删除的数之和为8,所以S=1,也就是说当选择这个子矩阵时,S的最大值为1。当然可以选择其他子矩阵来获取更大的S。 【输入数据】 输入文件matrix.in:输入从文件中读取,输入共n+1行。 第一行包含 4 个整数 n、m、p、q (1≤n,m≤1000,1≤p≤n,1≤q≤m),每两个整数之间用一个空格隔开。 接下来n行,每行包含 m 个整数。第i+1行的第j 个整数为Wij(1≤Wij≤100),表示矩 阵中的第i 行第j 列的数,每两个整数之间用一个空格隔开。 【输出数据】 输出文件matrix.out:结果输出到文件中。 输出共一行,包含一个整数,表示最大的S。注意不需要输出你选择的子矩阵。 【输入输出样例】 matrix.in 3 4 2 3 1 5 2 3 2 3 4 2 8 2 4 3 matrix.out 13 【样例解释】 当选择如下子矩阵时,S的值为13,满足最大。 【数据范围约定】 对于30%的数据保证1≤n≤50,1≤m≤50。 对于70%的数据保证1≤n≤300,1≤m≤300。 对于100%的数据保证1≤n≤1000,1≤m≤1000。 另外,所有的数据保证1≤p≤n,1≤q≤m,1≤Wij≤100。 【问题分析】 给出一个二维矩阵,要求从中选取一个p行q列的子矩阵,使 奇数列的和 与 偶数列的和 的差最大。 【算法分析】 对于30%的数据,暴力枚举,时间复杂度为O(n*m*p*q)。 对于70%的数据,用前缀和进行优化,然后进行暴力枚举,时间复杂度为O(n*m*q)。 对于100%的数据,用前缀和进行优化,进行枚举时,不暴力求值,因为只要把左边那列去掉,把右边那列加上即可,时间复杂度为O(n*m)。 【参考程序】 var n,m,p,q,i,j,s1,s2,ans:longint; a:array[0..1000,1..1000] of longint; begin assign(input,'matrix.in'); reset(input); assign(output,'matrix.out'); rewrite(output); read(n,m,p,q); for i:=1 to n do for j:=1 to m do begin read(a[i,j]); a[i,j]:=a[i,j]+a[i-1,j] end; for i:=1 to n-p+1 do begin s1:=0; s2:=0; for j:=1 to q do if odd(j) then s1:=s1+a[i+p-1,j]-a[i-1,j] else s2:=s2+a[i+p-1,j]-a[i-1,j]; if abs(s1-s2) > ans then ans:=abs(s1-s2); for j:=q+1 to m do begin if odd(j) then s1:=s1+a[i+p-1,j]-a[i-1,j] else s2:=s2+a[i+p-1,j]-a[i-1,j]; if odd(j-q) then s1:=s1-a[i+p-1,j-q]+a[i-1,j-q] else s2:=s2-a[i+p-1,j-q]+a[i-1,j-q]; if abs(s1-s2) > ans then ans:=abs(s1-s2) end end; writeln(ans); close(input); close(output) end.