题1:守望者的逃离
恶魔猎手尤迫安野心勃勃.他背叛了暗夜精灵,率深藏在海底的那加企图叛变:守望者在与尤迪安的交锋中遭遇了围杀.被困在一个荒芜的大岛上。为了杀死守望者,尤迪安开始对这个荒岛施咒,这座岛很快就会沉下去,到那时,刀上的所有人都会遇难:守望者的跑步速度,为17m/s, 以这样的速度是无法逃离荒岛的。庆幸的是守望者拥有闪烁法术,可在1s内移动60m,不过每次使用闪烁法术都会消耗魔法值10点。守望者的魔法值恢复的速度为4点/s,只有处在原地休息状态时才能恢复。
现在已知守望者的魔法初值M,他所在的初始位置与岛的出口之间的距离S,岛沉没的时间T。你的任务是写一个程序帮助守望者计算如何在最短的时间内逃离荒岛,若不能逃出,则输出守望者在剩下的时间内能走的最远距离。注意:守望者跑步、闪烁或休息活动均以秒(s)为单位。且每次活动的持续时间为整数秒。距离的单位为米(m)。
输入
输入文件escape.in仅一行,包括空格隔开的三个非负整数M,S,T。
输出
输出文件escape.out包含两行:
第1行为字符串"Yes"或"No" (区分大小写),即守望者是否能逃离荒岛。
第2行包含一个整数,第一行为"Yes" (区分大小写)时表示守望着逃离荒岛的最短时间
第一行为"No" (区分大小写) 时表示守望者能走的最远距离。
样例输入 复制
39 200 4
样例输出 复制
No 197
提示
30%的数据满足: 1 <= T<= 10, 1 <=S<= 100
50%的数据满足: 1 <= T <= 1000, 1 <= S <= 10000
100%的数据满足: 1 <= T <= 300000, 0 <= M<=1000 1 <=S <= 10^8
思路:能用魔法就魔法(因为魔法走的快),建立一个数组,记录每秒钟走的路程,使用一个循环,记录使用魔法闪烁获得的结果,使用第二个循环(第二个循环是使用走路的方式),使二者进行对比,看谁在相同的时间内,走的路程更远,就选择谁。
AC码:
//守望者的逃离
#include<stdio.h>
long long dp[300010];
long long max(long long a,long long b)
{
return a>b?a:b;
}
int main()
{
long long m; scanf("%lld",&m);
unsigned long long s; scanf("%llu",&s);
long long t; scanf("%lld",&t);
dp[0]=0;
for (int i=1;i<=t;++i)
{
if (m>=10)//少了个等于一直错
{
dp[i]=dp[i-1]+60;
m-=10;
}
else//法力值不够了,开始休息
{
dp[i]=dp[i-1];
m+=4;
}
}
for (int i=1;i<=t;++i)//判断走路的情况
{
if (dp[i]<dp[i-1]+17)//如果在规定时间内,魔法没有走路远,就改用走路
{
dp[i]=dp[i-1]+17;
}
if (dp[i]>=s)//如果距离超过了与出口之间的距离,就结束循环并输出结果
{
printf("Yes\n%d",i);
return 0;
}
}
printf("No\n%lld",dp[t]);//如果没有逃出岛,就输出最远距离
return 0;
}
题2:修理牛棚
题目描述
在一个暴风雨的夜晚,农民约翰的牛棚的屋顶、门被吹飞了。 好在许多牛正在度假,所以牛棚没有住满。 剩下的牛一个紧挨着另一个被排成一行来过夜。 有些牛棚里有牛,有些没有。 所有的牛棚有相同的宽度。 自门遗失以后,农民约翰很快在牛棚之前竖立起新的木板。 他的新木材供应者将会供应他任何他想要的长度,但是供应者只能提供有限数目的木板。 农民约翰想将他购买的木板总长度减到最少。 给出 M(1<= M<=50),可能买到的木板最大的数目;S(1<= S<=200),牛棚的总数;C(1 <= C <=S) 牛棚里牛的数目,和牛所在的牛棚的编号stall_number(1 <= stall_number <= S),计算拦住所有有牛的牛棚所需木板的最小总长度。 输出所需木板的最小总长度作为的答案。
输入
第 1 行: M , S 和 C(用空格分开) 第 2 到 C+1行: 每行包含一个整数,表示牛所占的牛棚的编号。
输出
单独的一行包含一个整数表示所需木板的最小总长度。
样例输入 复制
4 50 18
3
4
6
8
14
15
16
17
21
25
26
27
30
31
40
41
42
43
样例输出 复制
25
提示
[ 一种最优的安排是用板拦住牛棚3-8,14-21,25-31,40-43.]
思路:一个木板对应一个牛棚的情况是最理想的,因此当木板数大于等于牛的数量时,结果就是牛的数量,当木板数小于牛的数量时,需要计算木板数与牛数量的差值,从而就知道有几个牛棚需要直接连接,要想连接木板的总长度最小,所以应该尽可能找距离相近的牛棚,因此我们可以把得到的牛棚的位置按照从小到大的顺序进行升序排序,从而开始选择。
//修理牛棚
#include<stdio.h>
#include<stdlib.h>
int compare(const void *a, const void *b) {
return *(int*)a - *(int*)b;
}
int main()
{
int m,s,c; scanf("%d %d %d",&m,&s,&c);
if (m>=c)
{
printf("%d",c);
return 0;
}
int dp[210];//存储两只牛之间的距离
int n[210];//存储牛的位置
for (int i=0;i<c;++i)
{
scanf("%d",&n[i]);
}
qsort(n, c, sizeof(int), compare);//进行升序排序
for (int i=0;i<c-1;++i)//呈现牛棚间的距离
{
dp[i]=n[i+1]-n[i]-1;
}
qsort(dp, c - 1, sizeof(int), compare);//将距离排序
int sum=c;
//木板总数小于牛的数量
int cnt=c-m; //缺少的个数,便于知道有几个牛棚需要连接
//找距离最小的牛棚
for (int j=0;j<cnt;++j)
{
sum+=dp[j];
}
printf("%d",sum);
return 0;
}
题3:三值排序
题目描述
排序是一种很频繁的计算任务。现在考虑最多只有三值的排序问题。一个实际的例子是,当我们给某项竞赛的优胜者按金银铜牌序的时候。 在这个任务中可能的值只有三种1,2和3。我们用交换的方法把他排成升序的。 写一个程序计算出,给定的一个1,2,3组成的数字序列,排成升序所需的最少交换次数。
输入
Line 1: N (1 <= N <= 1000) Lines 2-N+1: 每行一个数字,共N行。(1..3)
输出
共一行,一个数字。表示排成升序所需的最少交换次数。
样例输入 复制
9
2
2
1
3
3
3
2
3
1
样例输出 复制
4
思路:将数据保存在一个数组中,统计1,2,3的数量,记为cnt1,cnt2,cnt3,使用一个循环,范围是0-cnt1,在这个范围内判断,如果数据的是1就继续进行,如果数据是2,就在中间段即cnt1-cnt1+cnt2之间寻找1,并交换,如果得到的数据是3,就在cnt2-最后,寻找1,并交换,完成交换后,0-cnt1已经全部是1,接下来就是将2和3交换位置,因此从cnt1-cnt1+cnt2之间找3,和第三个阶段的数中的2交换,并记录次数
//三值排序
#include <stdio.h>
int main() {
int n;
scanf("%d", &n);
int a[1001];
int res=0;
int cnt1=0,cnt2=0,cnt3=0;
for (int i=0;i<n;++i)
{
scanf("%d",&a[i]);
}
for (int i=0;i<n;++i)
{
if (a[i]==1)
{
cnt1++;
}
else if (a[i]==2)
{
cnt2++;
}
else if (a[i]==3)
{
cnt3 ++;
}
}
for (int i=0;i<cnt1;++i)
{
if (a[i]==2)
{
for (int j=cnt1;j<n;++j)
{
if(a[j]==1)
{
int temp=a[i];
a[i]=a[j];
a[j]=temp;
res++;
break;
}
}
}
else if(a[i]==3)
{
for (int j=n-1;j>=cnt1;j--)
{
if(a[j]==1)
{
int temp=a[i];
a[i]=a[j];
a[j]=temp;
res++;
break;
}
}
}
}
for (int i=cnt1;i<cnt1+cnt2;++i)
{
if(a[i]==3)
{
for (int j=cnt1+cnt2;j<n;++j)
{
if (a[j]==2)
{
int temp=a[i];
a[i]=a[j];
a[j]=temp;
res++;
break;
}
}
}
}
printf("%d",res);
return 0;
}
题4:聪明的LJY
题目描述
在我还是一个小小小的程序猿时(虽然现在还是小小的程序猿的。。。),LJY他就很聪明了,可是他怎么教我都有不会做的题。。。
有一天,我被学校指派了任务,要去zjj的m个地方买东西,惨了我这老胳膊老腿。这是LJY看到我愁眉苦脸,走了过来,拿出zjj的地图把它神奇的分为100*100的网格,使每个我要去的目的地都落在网格之中(假设每个地方都不重叠),然后他说只要你在这些网格中任意选一个,你到各个目的地的总距离就会最小,我就百思不得其解了。
同样聪明的你们,能帮我解决问题吗?求出最短总距离。(注意:因为地形复杂,只能向横纵方向行走)
输入
第一行一个整数n<20,表示有n组测试数据,下面是n组数据;
每组第一行一个整数m<20,表示本组有m个目的地,下面的m行每行有两个整数0<=x,y<=100,表示某个目的地的坐标。
m行后是新一组的数据;
输出
每组数据输出到最小的距离和,回车结束;
样例输入 复制
2
3
1 1
2 1
1 2
5
2 9
5 20
11 9
1 1
1 20
样例输出 复制
2
44
提示
设a(x1,y1),b(x2,y2),d|ab|=|x1-x2|+|y1-y2|.
思路:找到目的地的x,y坐标的中位数,并且遍历x,y数组找到最小距离
//聪明的LJY
#include <stdio.h>
#include<stdlib.h>
#include<math.h>
int cmp(int *a,int * b)
{
return *(int *)a -*(int *)b;
}
int main() {
int t; scanf("%d",&t);
while (t--)
{
int n;
scanf("%d",&n);
int a[110],b[110];
for (int i=0;i<n;++i)
{
scanf("%d %d", &a[i], &b[i]);
}
qsort(a,n,sizeof(int ),cmp);
qsort(b,n,sizeof(int ),cmp);
int mida=a[n/2];
int midb=b[n/2];
int total=0;
for (int i=0;i<n;++i)
{
total+=abs(a[i]-mida)+abs(b[i]-midb);
}
printf("%d\n",total);
}
return 0;
}