您的位置:首页 > 其它

河南省第一届大学生程序设计大赛解题报告

2013-04-21 00:10 302 查看
【试题一】

灾区已经非常困难,灾民需要帐篷、衣物、食品和血浆。可通往灾区的道路到处都是塌方,70%以上的路面损坏,桥梁全部被毁。中国空军立即启动应急预案,展开史上最大强度非作战空运行动,准备向灾区空投急需物资。由于余震不断,天气恶劣,怎样知道空投的物资是否落在某灾区的区域内呢?

经过空中观测,某灾区为一凸多边形,空投的物资落在P(X,Y)点。你能否给出一个正确判断?

【标准输入】

第1行: N X Y (N为凸形的边数,X,Y为空投物资的坐标 )

第2行: X1 Y1 X2 Y2…….Xn Yn (逆序给出的N个顶点坐标 )

【标准输出】

YES (物资落在灾区的区域内 )



NO (物资落在灾区的区域外 )

【约束条件】

(1) 3 ≤N ≤ 20

(2) 所有的坐标Xi和Yi为整数 -10000≤ Xi ,Yi ≤10000

(3) X,Y为整数 -10000≤ X ,Y ≤10000

(4) 时间限制: 1000MS

【 样 例 】

标准输入

4 2 2

-1 0 3 -2 10 9 -1 110

标准输出

YES

题目分析:求一个给定的点A(x0,y0)是否在凸多边型p0p1...pn-1(逆序给出)内部,我们首先想到的是判断一个三角形三个点是顺时针还是逆时针的,我们可以利用这个结论。

看下图:


如果点A在多边形内部,则三角形APiP(i+1%n)必为逆时针,而如果在外部,则有些点和A组成的三角形是顺序的,多以,我们只需要依次判断APiP(i+1%n)是否为逆时针即可,一旦发现不是逆时针,则说明在凸多边型外部!

那么我们来看怎么判断三角形的正序还是逆序呢?我们有以下结论:定义向量AB=(x1,y1),AC=(x2,y2),则:

AB X AC>0 逆时针

AB X AC<0 顺时针,其中运算X(向量叉乘)定义为x1*y2-x2*y1。

贴上代码:

#include<stdio.h>
#define N 25
struct node {
int x,y;
}p
;

int fun(struct node a, struct node b,struct node c) {
int abx,aby,acx,acy,ans;
abx=b.x-a.x;
aby=b.y-a.y;
acx=c.x-a.x;
acy=c.y-a.y;
ans=abx*acy-aby*acx;
if(ans>0) return 1;
else return 0;

}
int main() {
int i,n,flag;
struct node a,b,c;
while(scanf("%d %d %d",&n,&a.x,&a.y)!=EOF) {
for(i=0;i<n;i++) {
scanf("%d %d",&p[i].x,&p[i].y);
}
for(i=0,flag=1;i<n;i++) {
b=p[i];
c=p[(i+1)%n];
flag=fun(a,b,c);
if(flag==0) break;
}
if(flag==1) printf("YES\n");
else printf("NO\n");
}
return 0;
}

/*
4 2 2
-1 0 3 -2 10 9 -1 110
*/


【试题二】

据不完全统计,受地震影响,四川大部分灾区通信陷入瘫痪,数千个基站因断电、传输中断等原因退出服务,目前总公司已紧急部署对受灾地区进行通信抢修。按照应急通信保障预案,必须尽快、付出代价最小,效率更高来全力恢复通信。

由于四川大部分灾区都处于山区,有很多基站之间不能直接建立通信。现已知建立各基站之间直接通信的代价,问如何建立总代价最小的通信网,使得任意两个基站之间都能通信?

【标准输入】

第1行: N (N为的个数 )

第2~N+1行: Pi1 Pi2 ……Pin (Pij为建立基站i与基站j直接通信的代价

i, j=1 , 2, …., N )

【标准输出】

T (建立通信网的最小代价数)

【约束条件】

(1) 10 ≤ N ≤1000

(2) -1 ≤ Pij ≤ 1000 Pij 为整数,若Pij = -1,表示基站i与基站j不能直接通信

(3) 时间限制: 1000MS

【 样 例 】

标准输入

5

0 160 30 20 -1

160 0 200 –1 –1

30 200 0 50 80

20 –1 50 0 70

-1 –1 80 70 0

标准输出

280

题目分析:将给出的矩阵图转化为由所有的边组成的数组,然后利用并查集,Prim算法搞定!不多说。。。

#include<stdio.h>
#include<string.h>
#include<stdlib.h>
#define N 1010
int map

,set
;

struct node {
int x,y;
int len;
int num;
}edge
;

int cmp(const void *a, const void *b) {
return (*(struct node *)a).len-(*(struct node *)b).len;
}

int find(int x) {
int r=x,i,j;
while(r!=edge[r].num) {
r=edge[r].num;
}

i=x;
while(edge[i].num!=r) {//路径压缩
j=edge[i].num;
edge[i].num=r;
i=edge[j].num;
}

return r;
}

int merge(int x, int y, int w) {
int x1,y1;
x1=find(x);
y1=find(y);
if(x1!=y1) {
edge[y1].num=x1;
return w;//返回代价
}
return 0;
}
int main() {
int n,i,j,k,sum;
while(scanf("%d",&n)!=EOF) {
memset(map,-1,sizeof(map));
for(i=0;i<n;i++)
for(j=0;j<n;j++) {
scanf("%d",&map[i][j]);
}
for(i=0,k=0;i<n;i++)
for(j=0;j<i;j++) {
if(i==j) continue;
if(map[i][j]!=-1) {
edge[k].x=i;
edge[k].y=j;
edge[k++].len=map[i][j];
}
}
qsort(edge,k,sizeof(edge[0]),cmp);
for(i=0;i<k;i++)//这个初始化并查集不能过早,否则出问题!
edge[i].num=i;
for(i=0,sum=0;i<k;i++) {
sum+=merge(edge[i].x,edge[i].y,edge[i].len);
}
printf("%d\n",sum);
}
return 0;
}

/*

5
0 160 30 20 -1
160 0 200 -1 -1
30 200 0 50 80
20 -1 50 0 70
-1 -1 80 70 0

280

*/


【试题三】

密码破译

某组织欲破获一个外星人的密码,密码由一定长度的字串组成。此组织拥有一些破译此密码的长度不同的钥匙,若两个钥匙的长度之和恰好为此密码的长度,则此密码被成功破译。现在就请你编程找出能破译此密码的两个钥匙。

【标准输入】

第一行: N N为钥匙的个数(1<=N<=1000)

第二行: L L为密码的长度

以下有N行: Ai 每行为一把钥匙的长度 i=1,2,……,N

【标准输出】

若无法找到破译此密码的钥匙,则输出0

若找到两把破译的钥匙,则输出文件有两行,分别为两把钥匙的编号,按从小到大输出。若有多种破译方案,则只输出包含起始编号最小的一组即可。

[【约束条件】

(1)1<= N,L,Ai <=1000 ( i=1, 2, ….., N )

(2)时间限制: 1000MS

【 样 例 】

标准输入

10

80

27

9

4

73

23

68

12

64

92

16

标准输出

6

7

题目分析:所以我感觉这题直接二重循环就出来了,时间复杂度不是很高,最多10^6,并且中间有很多情况可以剪去!由于没有标准答案,也不知道合格不。。。

#include<stdio.h>
#define N 1100
int len
;
int main() {
int i,j,sum,n,s,flag;
while(scanf("%d",&n)!=EOF) {
scanf("%d",&s);
for(i=0;i<n;i++) {
scanf("%d",&len[i]);
}
for(i=0,flag=0;i<n&&len[i]<s;i++) {
for(j=i+1;len[i]+len[j]<=s;j++){
if(len[i]+len[j]==s) {
printf("%d\n%d\n",i+1,j+1);
flag=1;
break;
}
}
if(flag==1) break;
}
if(flag==0)
printf("0\n");
}
return 0;
}


【试题四】

在灾区,多数人已经受伤,缺水,少食物,精神处在崩溃的边缘。很多人的生存条件仅能维持几天。灾民需要帐篷、衣物、食品和医疗器材、药品等物资。14日上午,中央军委委员、空军司令员许其亮组织召开空军首长办公会,将空军下一步救灾重点确定为抢救伤员、空投、空运。空军各部队都派出多架运输机,准备向灾区空运急需物品。

现在已知四种打包过的急需物品重量分别为C1, C2, C3,C4 ,数量分别为M1,M2,M3,M4包。一架运输机的载重量为W, 现在各部队关心将一架运输机装满共有多少种运载方案,以便调度进行空运。

比如C={ 100, 200, 500, 1000}, M={ 3, 2, 3, 1 }, W=1000, 一共有4种运载方案:

1000=100+100+100+200+500

1000=100+200+200+500

1000=500+500

1000=1000

【标准输入】

第一行: C1 C2 C3 C4 N 其中 N为空运的部队数

接下来n行: Mi1 Mi2 Mi3 Mi4 Wi 表示各运载部队需空运的4种物品数量Mi

和各自运输机的载重量Wi i=1,2,….. , N

【标准输出】

输出有N行,表示各部队运载物品的方案总数,保证答案在10000范围内

【约束条件】

(1)0< Cj <= 1000 0 <= Mij <= 500 i =1,2,….. , N j =1,2,3,4

(2)N<=1000 0 < Wi <= 100000 i =1,2,….. , N

(3)时间限制: 1000MS

【 样 例 】

标准输入

1 2 5 10 2

3 2 3 1 10

1000 2 2 2 900

标准输出

4

27

由于让求有多少种方案,所以首先想到的是母函数,如果是求能否完成装载任务的话也可以用多重背包来做。

代码:

#include<stdio.h>
#include<string.h>
#include<stdlib.h>
#define N 100010
int c1[N+10],c2[N+10],c[4],m[4];

int main() {
int i,n,j,k,w;
while(scanf("%d %d %d %d %d",&c[0],&c[1],&c[2],&c[3],&n)!=EOF) {
while(n--) {
for(i=0;i<4;i++) {
scanf("%d",&m[i]);
}
scanf("%d",&w);
memset(c1,0,sizeof(int)*(w+10));
memset(c2,0,sizeof(int)*(w+10));
for(i=0,j=0;i<=m[0];i++,j+=c[0])
c1[j]=1;
for(i=1;i<4;i++){
for(j=0;j<=w;j++) {
if(c1[j]==0) continue;
for(k=0;k+j<=w&&k<=m[i];k++) {
c2[k*c[i]+j]+=c1[j];
}
}
for(j=0;j<=w;j++) {
c1[j]=c2[j];
c2[j]=0;
}
}
printf("%d\n",c1[w]);
}

}
return 0;
}
/*
1 2 5 10 2
3 2 3 1 10
1000 2 2 2 900

4
27
*/


【试题五】

从5月12日下午地震发生至今已经超过48小时,根据地震救灾的常识推算,未来24小时将是救灾最后的黄金时间。时间在无情的流逝,数以万计的灾民依旧命悬喘息之间。现在,数万军民正日夜奋战在抢救灾民第一线。从人员的组织协调到救灾物资的后援运输,每一个环节都直接关系到救灾的效果好坏。

由于通往各灾区的道路完全中断,大批救援物资只好空投到各个灾区。某军区准备了一批物资, 恰好能均分到处于环形的N个灾区中。遗憾的是,由于余震不断,天气恶劣等原因,落到各灾区的数量不相同。

正如温家宝总理所一再强调的“抢救人的生命,是这次救灾工作的重中之重” 。为了保证救灾的效率不会平白消耗, 当地的民间救助组织可以选择将落到自己所在区的物资传送到左边或者右边相邻的灾区。为了公平起见,我们希望通过相邻灾区的相互传送,最终使所有的灾区获得相同数量的物资。假设一个物资从一个灾区传送到另一个灾区付出的代价是1, 问怎样进行传送,使得所付出的总代价最小。

【标准输入】

第一行: N 表示处于环形的灾区数

接下来n行: 每行一个整数Ai, 表示第i个灾区得到的物质数量。

【标准输出】

输出只有一个数, 表示传送物资付出的最小总代价

【约束条件】

(1) N<=1000000

(2) Ai>=0, 保证Ai在长整型范围内, Ai的总和在int64/long long范围内.

(3)时间限制: 1000MS

【 样 例 】

标准输入

4

4 1 2 5

标准输出

4

分析:对于这个题,我们建立如下的模型。



因为任意一个方程都可以由其他四个方程推得,所以可以随意舍弃一个方程,这里我们舍弃方程一,则其他的四个方程都可以由方程一c0表示。那么,我们要求的最小代价就是|c0|+|c1|+|c2|+|c3|+|c4|,这四个点的位置因为c0的取值不同,在X轴上分布的位置也不同(但是c1-c4之间的相对大小不会因为c0取值变化改变而改变),所以,当原点出现在c0-c4的中间位置时,绝对值之和最小,也就是c0,c1,c2,c3,c4的中位数的位置。所以,我们就可以很容易求出来了!

代码:

#include<stdio.h>
#include<string.h>
#include<stdlib.h>
#define N 1000010
int a[N+10],c[N+10];

int cmp(const void *a, const void *b) {
return *(int *)a-*(int *)b;
}
int main() {
int n,i,j,m,min;
long long sum;
while(scanf("%d",&n)!=EOF) {
for(i=0,sum=0;i<n;i++) {
scanf("%d",&a[i]);
sum+=a[i];
}
m=sum/n;
for(i=1,c[0]=0;i<n;i++) {//c[0]可以初始化为任何值,结果不变
c[i]=c[i-1]+a[i]-m;
}
qsort(c,n,sizeof(int),cmp);
for(i=0,j=n-1,min=0;i<j;i++,j--){
min+=c[j]-c[i];
}
printf("%d\n",min);
}
return 0;
}

/*
4
1 2 5 4

4
*/


【试题六】 Time Limit: 1000MS

灾情就是命令,时间就是生命,救灾部队要以最快的速度赶到救灾现场。13日10时,成都军区抗震救灾联合指挥部里,成都军区司令员李世明大声命令:“不管将军还是士兵,告诉大家,谁先到就给谁立功!”

We may assume that all the soldier except "Yongshi" run from Chengdu to Wenchuan at a fixed speed. Yongshi is a soldier with a different running habit – he always tries to follow another soldier to avoid running alone. When Yongshi gets to Chengdu , he will
look for someone who is setting off to Wenchuan. If he finds someone, he will follow that soldier, or if not, he will wait for someone to follow. On the way from Chengdu to Wencuan, at any time if a faster soldier surpassed Yongshi , he will leave the soldier
he is following and speed up to follow the faster one. We assume the distance from Chengdu to Wenchuan is 95 kilometers and the time that Yongshi gets to Chengdu is zero. Given the set off time and speed of the other soldier, your task is to give the time
when Yongshi arrives at Wenchuan.

【Input】

There are several test cases (<=10 test cases). The first line of each case is N (1 <= N <= 1000) representing the number of soldier (excluding Yongshi ). N = 0 ends the input. The following N lines are information of N different soldiers, in such format: Vi
Ti Vi is a positive integer <= 30, indicating the speed of the i-th soldier (kph, kilometers per hour). Ti is the set off time of the i-th soldier, which is an integer and counted in minutes. In any case it is assured that there always exists a nonnegative
Ti. -1000<= Ti <=1000

【Output 】

Output one line for each case: the arrival time of Yongshi. Round up (ceiling) the value when dealing with a fraction.

Sample Input

4

10 0

12 -15

15 19

30 24

2

21 0

22 34

0

Sample Output

214

271

我感觉这个题目比较麻烦,需要考虑很周全,但是没有牵扯什么算法,就是一般的数据处理。

#include<stdio.h>
#include<string.h>
#include<math.h>
#define N 1010
struct node {
double v,t,p;
}set[N+10];

int main() {
int i,n,v,t,num;
double mint,sumt,s=95,t0;
while(scanf("%d",&n)!=EOF) {
memset(set,0,sizeof(set));
for(i=1;i<=n;i++){
scanf("%d %d",&v,&t);
set[i].t=1.0*t;
set[i].v=1.0*v/60;
}
for(i=0;i<=n;i++) {
set[i].p=-set[i].t*set[i].v;
}
sumt=num=0;
while(set[0].p-s<0){
for(i=1,mint=0x7FFFFFFF;i<=n;i++){
if(set[i].p<=set[0].p&&set[i].v>set[0].v) {
t0=(set[0].p-set[i].p)/(set[i].v-set[0].v);
if(t0<mint && num!=i){
mint=t0;
num=i;
}
}
}
if(set[0].p+mint*set[0].v>s){
sumt+=(s-set[0].p)/set[0].v;
break;
}
for(i=0;i<=n;i++) {
set[i].p+=set[i].v*mint;
}
set[0].v=set[num].v;
sumt+=mint;
}
printf("%.0lf\n",sumt);
}
return 0;
}
/*
4
10 0
12 -15
15 19
30 24

2
21 0
22 34

214
271
*/


【试题八】

An ascending sorted sequence of distinct values is one in which some form of a less-than operator is used to order the elements from smallest to largest. For example, the sorted sequence A, B, C, D implies that A < B, B < C and C < D. in this problem, we will
give you a set of relations of the form A < B and ask you to determine whether a sorted order has been specified or not.

【Input】

Input consists of multiple problem instances. Each instance starts with a line containing two positive integers n and m. the first value indicated the number of objects to sort, where 2 <= n <= 26. The objects to be sorted will be the first n characters of
the uppercase alphabet. The second value m indicates the number of relations of the form A < B which will be given in this problem instance. 1 <= m <= 100. Next will be m lines, each containing one such relation consisting of three characters: an uppercase
letter, the character "<" and a second uppercase letter. No letter will be outside the range of the first n letters of the alphabet. Values of n = m = 0 indicate end of input.

【Output】

For each problem instance, output consists of one line. This line should be one of the following three:

Sorted sequence determined: y y y… y. Sorted sequence cannot be determined. Inconsistency found.

y y y… y is the sorted, ascending sequence.

Sample Input 4 6

A<B

A<C

B<C

C<D

B<D

A<B

3 2

A<B

B<A

26 1

A<Z

0 0

Sample Output

Sorted sequence determined: A B C D.

Inconsistency found.

Sorted sequence cannot be determined.

题目大意:给出A、B、C。。。之间的制约关系,求能否按序列输出。

解析:实际上是拓扑排序,注意输入的关系比如A<B 可能有重复,要注意排除。

#include<stdio.h>
#include<string.h>
#include<stdlib.h>
#define N 30
struct node {
int num;
struct node *next;
}*p,*q;
struct Lnode {
int d,num,use;
struct node *next;
}set
;
int res
;
int topSort(int n) {
int i,k=n,cnt,num;
for(i=0,cnt=0;i<n;i++){
if(set[i].use==1&&set[i].d==0){
cnt++;
num=i;
}
}
while(k>0){
if(cnt>1) return 2;
if(cnt==0) return 0;
set[num].use=0;//已经排好的和未出现的点都在剔除掉
res[k--]=num;
for(p=set[num].next,cnt=0;p!=NULL;p=p->next) {
set[p->num].d--;
if(set[p->num].use==1&&set[p->num].d==0) {
cnt++;
num=set[p->num].num;
}
}
}
return 1;

}
int main() {
int n,m,i,num1,num2,temp,ans,flag;
char s[3];
while(scanf("%d %d",&n,&m),n||m) {
for(i=0;i<n;i++) {
set[i].d=0;
set[i].num=i;
set[i].use=1;
set[i].next=NULL;
}
for(i=0;i<m;i++) {
scanf("%s",s);
num1=s[0]-'A';
num2=s[2]-'A';
if(num1==num2)
continue;
if(s[1]=='>') {
temp=num2;
num2=num1;
num1=temp;
}
for(q=set[num1].next,flag=0;q!=NULL;q=q->next) {
if(q->num==num2) {
flag=1;
break;
}
}
if(flag==1)
continue;
p=(struct node *)malloc(sizeof(struct node));
p->num=num2;
set[num2].d++;
p->next=set[num1].next;//头插法建立链表
set[num1].next=p;
}
ans=topSort(n);
if(ans==0)
printf("Inconsistency found.\n");
else if(ans==2)
printf("Sorted sequence cannot be determined.\n");
else {
printf("Sorted sequence determined:");
for(i=n;i>1;i--) {
printf("%c ",'A'+res[i]);
}
printf("%c.\n",'A'+res[i]);
}
}
return 0;
}
/*
4 6
A<B
A<C
B<C
C<D
B<D
A<B
3 2
A<B
B<A
26 1
A<Z
0 0
Sorted sequence determined: A B C D.
Inconsistency found.
Sorted sequence cannot be determined.
*/
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: 
相关文章推荐