B - 补提交卡
蒜头君给自己定了一个宏伟的目标:连续
100
天每天坚持在计蒜客题库提交一个程序。
100
天过去了,蒜头君查看自己的提交记录发现有
N
天因为贪玩忘记提交了。于是蒜头君软磨硬泡、强忍着花椰菜鄙视的眼神从花椰菜那里要来
M
张 “补提交卡”。每张 “补提交卡” 都可以补回一天的提交,将原本没有提交程序的一天变成有提交程序的一天。蒜头君想知道通过利用这
M
张补提交卡,可以使自己的 “最长连续提交天数” 最多变成多少天。
输入格式
输出格式
对于每组数据,输出通过使用补提交卡蒜头君的最长连续提交天数最多变成多少。
Sample Input
3
5 1
34 77 82 83 84
5 2
10 30 55 56 90
5 10
10 30 55 56 90
Sample Output
76
59
100
思路 就是找差n 数据间的差值
关键在于考虑第一个数据和最后一个数据 所以加a[0]=0;
a[n+1]=101;很关键
#include<stdio.h>
int a[1010];
int main()
{
int n,m,x;
int i,j;
int cnt,max;
scanf("%d",&x);
while(x--)
{
scanf("%d %d",&n,&m);
for(i=1;i<=n;i++)
scanf("%d",&a[i]);
if(m>=n)
{
printf("100\n");
continue;
}
max=0;
a[0]=0;
a[n+1]=101;
for(i=1;i<=n-m+1;i++)
{
cnt=a[i+m]-a[i-1]-1;
//printf("cnt=%d\n",cnt);
if(cnt>max)
max=cnt;
}
printf("%d\n",max);
}
}
E - 数列极差
佳佳的老师在黑板上写了一个由 n 个正整数组成的数列,要求佳佳进行如下操作:每次擦去其中的两个数 a 和 b,然后在数列中加入一个数 a×b+1,如此下去直至黑板上剩下一个数为止,在所有按这种操作方式最后得到的数中,最大的为 max,最小的为 min, 则该数列的极差定义为 M=max−min。
由于佳佳忙于准备期末考试,现请你帮助他,对于给定的数列,计算出相应的极差 M。
输入格式
第一行为一个正整数 n 表示正整数序列的长度;
在接下来的 n 行中,每行输入一个正整数。
接下来的一行有一个 0,表示数据结束。
输出格式
输出只有一行,为相应的极差 d。
样例
Input Output
3
1
2
3
0
2
数据范围与提示
对于全部数据,0≤n≤50000,保证所有数据计算均在 32 位有符号整数范围内
贪心思想:每次选最小的运算 注意新算出来的数据需要与剩下的数据重新排序选择最小的
#include<stdio.h>
void quick_sort1(int left,int right,int a[])
{
int i,j,temp,t;
if(left>right)
return;
temp=a[left];
i=left;
j=right;
while(i!=j)
{
while(a[j]>=temp&&i<j)
j--;
while(a[i]<=temp&&i<j)
i++;
//没相遇时交换
if(i<j)
{
t=a[i];
a[i]=a[j];
a[j]=t;
}
}
a[left]=a[i];
a[i]=temp;
quick_sort1(left,i-1,a);
quick_sort1(i+1,right,a);
return;
}
void quick_sort2(int left,int right,int a[])
{
int i,j,temp,t;
if(left>right)
return;
temp=a[left];
i=left;
j=right;
while(i!=j)
{
while(a[j]<=temp&&i<j)
j--;
while(a[i]>=temp&&i<j)
i++;
//没相遇时交换
if(i<j)
{
t=a[i];
a[i]=a[j];
a[j]=t;
}
}
a[left]=a[i];
a[i]=temp;
quick_sort2(left,i-1,a);
quick_sort2(i+1,right,a);
return;
}
int main()
{
int a[1010],b[1010],n;
int x,i,cnt=0,ans,sum1,sum2;
scanf("%d",&n);
for(i=0;i<n;i++)
scanf("%d",&a[i]);
//quick_sort(0,cnt-1);
for(i=0;i<=n;i++)
{
b[i]=a[i];
}
quick_sort2(0,n-1,b);
quick_sort1(0,n-1,a);
/*for(i=0;i<n;i++)
{
printf("%d ",b[i]);
}*/
//for(i=0;i<cnt;i++)
//printf("%d ",a[i]);
for(i=0;i<=n-2;i++)
{
a[i+1]=a[i]*a[i+1]+1;
b[i+1]=b[i]*b[i+1]+1;
quick_sort1(i+1,n-1,a);
quick_sort2(i+1,n-1,b);
}
//printf("%d %d",a[n-1],b[n-1]);
printf("%d",a[n-1]-b[n-1]);
}
过河
UCAS_ACM小组的N名成员外出旅游,结果在路上碰到了一条河,岸边只有一艘船,这艘船最多只能载两人。
已知N名成员每人有一个过河时间ti,每次划船过河的时间等于船上成员的过河时间的最大值。请你找N名成员全部到底对岸的最少耗时。
输入
输入包含多组测试数据。第一行含有一个正整数T,表示数据组数。
每组数据的第一行含有一个整数N。接下来的一行含有N个整数,表示ti。
输出
对于每组输入数据输出一行,每行包括1个整数,代表该组数据下到对岸的最少耗时。
样例输入
2
4
1 2 5 10
5
1 2 8 7 6
样例输出
17
22
数据范围
1≤T≤20
1≤N≤1000
1≤ti≤100
提示
船划到对岸后不会自动飘回来的哦~
n>=4 时分两种情况 选择两种情况中时间较短的那个(每次会送去两个人 所以递推n-=2)
一种情况是 最快的和最慢去 最快的回来 最快的和次慢的去 最快的回来
另一种情况 最快的和次快的去 最快的回来 然后最慢的和次慢的去 次快的回来
n=3时 为三个时间的总和
n=2时 为较快的那个时间
#include<stdio.h>
int a[1010];
void quick_sort(int left,int right)
{
int i,j,temp,t;
if(left>right)
return;
temp=a[left];
i=left;
j=right;
while(i!=j)
{
while(a[j]>=temp&&i<j)
j--;
while(a[i]<=temp&&i<j)
i++;
//没相遇时交换
if(i<j)
{
t=a[i];
a[i]=a[j];
a[j]=t;
}
}
a[left]=a[i];
a[i]=temp;
quick_sort(left,i-1);
quick_sort(i+1,right);
return;
}
int min(int x,int y)
{
int m;
m=x;
if(y<x)
m=y;
return m;
}
int main()
{
int x;
int ans,i,j,s1,s2;
scanf("%d",&x);
while(x--)
{ int n;
ans=0,s1=0,s2=0;
scanf("%d",&n);
for(i=1;i<=n;i++)
scanf("%d",&a[i]);
//sort(a,a+n);
quick_sort(1,n);
while(n>0)
{
if(n>=4)
{ s1=a[n]+a[n-1]+a[1]+a[1];
s2=a[1]+a[2]+a[n]+a[2];
ans+=min(s1,s2);
n=n-2;
}
else if(n==3)
{ ans+=a[1]+a[2]+a[3];
n=n-3;
}
else if(n<=2)
{
ans+=a[n];
n=n-2;}
}printf("%d\n",ans);
}
}
H - 超市
超市里有N个商品. 第i个商品必须在保质期(第di天)之前卖掉, 若卖掉可让超市获得pi的利润.
每天只能卖一个商品.
现在你要让超市获得最大的利润.
(原题说明过于抽象)
Input
多组数据.
每组数据第一行为N, 即超市的商品数目
之后N行数字. 第i行为 pi, di
N , pi, di <= 10000
Output
对于每一组数据, 输出当前条件下超市的最大利润
Sample Input
4
50 2
10 1
20 2
30 1
7
20 1
2 1
10 3
100 2
8 2
5 20
50 10
Sample Output
80
185
思路:以钱来排序 从一遍历对应时间 有空闲天数即可卖出
book用于标记是否卖出
#include<stdio.h>
#include<algorithm>
using namespace std;
int book[100001];
struct fact
{
int money;
int time;
}a[100001];
bool cmp(struct fact x,struct fact y)
{
return x.money>y.money;
}
int main()
{
int n,i,j,ans;
while(scanf("%d",&n)!=EOF)
{
ans=0;
for(i=0;i<n;i++)
scanf("%d %d",&a[i].money,&a[i].time);
sort(a,a+n,cmp);
//for(i=0;i<n;i++)
//printf("%d ",a[i].money);
for(i=0;i<n;i++)
for(j=a[i].time;j>=1;j--)
{
if(book[j]==0)
{
book[j]=1;
ans+=a[i].money ;
break;
}
}
printf("%d\n",ans);
for(i=0;i<=10000;i++)
book[i]=0;
}
return 0;
}
O - 拯救X先生
话说上回讲到海东集团面临内外交困,公司的元老也只剩下XHD夫妇二人了。显然,作为多年拼搏的商人,XHD不会坐以待毙的。
一天,当他正在苦思冥想解困良策的时候,突然想到了自己的传家宝,那是公司成立的时候,父亲作为贺礼送来的一个锦囊,徐父当时交代,不到万不得已的时候,不要打开它。“现在不正是最需要的时候吗?”,一边想,XHD一边找到了这个精心保管的锦囊,打开一看,里面只有一句话“杭城北麓千人洞有宝”。
二话不说,XHD拿起一个大口袋就出发了,这个千人洞他是知道的,小的时候,爸爸曾经带他来过这个隐蔽的路口,并告诉他,这是千人洞。他现在才明白爸爸当初这句话的含义。
尽管有点印象,XHD还是花了很大的精力才找到这个异常隐蔽的洞口,走进一看,几乎惊呆了,真的是眼花缭乱!不过尽管宝贝的种类不少,但是每种宝贝的量并不多,当然,每种宝贝单位体积的价格也不一样,为了挽救HDU,现在请你帮忙尽快计算出来XHD最多能带回多少价值的宝贝?(假设宝贝可以分割,分割后的价值和对应的体积成正比)
Input
输入包含多个测试实例,每个实例的第一行是两个整数v和n(v,n<100),分别表示口袋的容量和宝贝的种类,接着的n行每行包含2个整数pi和mi(0<pi,mi<10),分别表示某种宝贝的单价和对应的体积,v为0的时候结束输入。
Output
对于每个测试实例,请输出XHD最多能取回多少价值的宝贝,每个实例的输出占一行。
Sample Input
2 2
3 1
2 3
0
思路:体积相减作为判断条件
#include<stdio.h>
#include<algorithm>
#include<cstdio>
using namespace std;
struct f
{
int price;
int v;
}a[1010];
bool cmp(f x, f y)
{
return x.price>y.price;
}
int main()
{
int n,m,ans,sum=0,count=0,i;
while(scanf("%d",&m)!=EOF)
{ if(m==0)
return 0;
sum=0,count=0;
scanf("%d",&n);
for(i=0;i<n;i++)
scanf("%d %d",&a[i].price,&a[i].v);
ans=0;
sort(a,a+n,cmp);
for(i=0;i<n;i++)
{
if(m>=a[i].v)
{
ans+=a[i].price*a[i].v;
m-=a[i].v;
if(m==0)
break;
}
else
{
ans+=(m*a[i].price);
break;
}
}
printf("%d\n",ans);
}
return 0;
}
奇怪的电梯
呵呵,有一天我做了一个梦,梦见了一种很奇怪的电梯。大楼的每一层楼都可以停电梯,而且第ii层楼(1 \le i \le N)(1≤i≤N)上有一个数字K_i(0 \le K_i \le N)K (0≤K i ≤N)。电梯只有四个按钮:开,关,上,下。上下的层数等于当前楼层上的那个数字。当然,如果不能满足要求,相应的按钮就会失灵。例如:3, 3 ,1 ,2 ,53,3,1,2,5代表了K_i(K_1=3,K_2=3,…)K
i (K1=3,K2 =3,…),从11楼开始。在11楼,按“上”可以到44楼,按“下”是不起作用的,因为没有-2−2楼。那么,从AA楼到BB楼至少要按几次按钮呢?
输入格式
共二行。
第一行为33个用空格隔开的正整数,表示N,A,B(1≤N≤200, 1≤A,B≤N)N,A,B(1≤N≤200,1≤A,B≤N)。
第二行为NN个用空格隔开的非负整数,表示K_iK i。
输出格式
一行,即最少按键次数,若无法到达,则输出-1−1。
输入输出样例
输入 #1复制
5 1 5
3 3 1 2 5
输出 #1复制
3
典型搜素问题 学习点 一 cnt 二模板 dfs()函数中 结束条件 标记=1(开始遍历) 满足条件下一步没标记的话 进行下一步搜素 否则取消标记
#include<stdio.h>
int x,y,cnt,m=10000,i,book[1010],a[1010],n,ans;
void dfs(int c)
{
if(cnt>=m)
return;
if(c==y)
{
m=cnt;
return;
}
book[c]=1;
cnt++;
if(c+a[c]<=n&&book[c+a[c]]==0)
dfs(c+a[c]);
if(c-a[c]>=1&&book[c-a[c]]==0)
dfs(c-a[c]);
cnt--;
book[c]=0;
}
int main()
{
while(scanf("%d",&n)!=EOF)
{
if(n==0)
return 0;
scanf("%d %d",&x,&y);
for(i=1;i<=n;i++)
scanf("%d",&a[i]);
dfs(x);
if(m==10000)
printf("-1\n");
else
printf("%d\n",m);}
}
(同样的题在洛谷能通过 vjudge平台上不行?)