预备役总结2021年1月20日
作者:互联网
2021年1月20日总结
今天学习了二分答案算法
一共过了两道题目花费了我6个小时
在这个问题之外首先今天学的一个在一本书上面看到的求a[i]<=k的最大i问题
#include<stdio.h>
#include<stdlib.h>
int qqsort(int *a,int start,int end)
{
if(start>=end)return 0;
int i=start;
int j=end;
int t=a[start];
while(i<j)
{
while(i<j&&a[j]>t)j--;
if(i<j)a[j]=a[i++];
while(i<j&&a[i]<t)i++;
if(i<j)a[i]=a[j--];
}
a[i]=t;
qqsort(a,start,i-1);
qqsort(a,i+1,end);
}
int solve(int *a,int start,int end,int key)
{
while(end-start>1)
{
int mid=(start+end)/2;
printf("%d\n",mid);
if(a[mid]>=key)
{
end=mid;
}
else
{
start=mid;
}
}
return end;
}
int main()
{
int *a;
int n;
scanf("%d",&n);
a=(int *)malloc(sizeof(int )*n);
for(int i=0;i<n;i++)
{
scanf("%d",a+i);
}
int k;
//for(int i=0;i<n;i++)
//printf("%d ",a[i]);
scanf("%d",&k);
qqsort(a,0,n-1);//排序出单调递增的数组
//开始二分搜索 输入一个k值求 a[i]>=k的最大i 不存就输出n
printf("%d\n",solve(a,-1,n,k)); //为什么为-1和n的原因是因为假如k为这个数组最小的数 那么如果是end会一直向右移动 一直移动到1 然后-1+1再除以2 就返回结果了
//假如不为-1 那么而为0最终搜索范围是在【1,n】
//也就是将我们搜索范围为【n,m】那么我们就要考虑最坏情况 假如搜索的结果是n 那么我们就应该考虑如何得到n 也就是(n+1+n-1)/2==n所有左边界
//应该为n-1 同理 有边界应该为m+1
}
写了很多注释的地方是我刚开始错的地方
想了好久终于是想通了 为什么不从0和n-1开始搜索
如上注释(呜呜呜!!)个人理解有错误往指出
现在就是今天的ac题
问题 A: 切绳子洛谷链接
描述
有n条绳子,长度分别为L[i]。如果从他们中切割出k条长度相同的绳子的话,这k条绳子每条最长能有多长?(答案保留小数点后两位(直接舍掉两位后的小数),规定1单位长度的绳子最多可以切割成100份)
格式
输入格式
包含多组输入
输入n,k,(1<=n,k<=10000)
然后n行,输入L[i],代表每一条绳子的长度(1<=L[i]<=100000)
输出格式
切出k条长度相等的绳子最大长度是多少,输出保留两位小数
样例
样例输入 Copy
4 11
8.02
7.43
4.57
5.39
样例输出 Copy
2.00
ac代码如下
#include<stdio.h>
int check(int *a,int n,int k,int ans)
{
int i;
int sum=0;
for(i=0;i<n;i++)
{
sum+=a[i]/ans;
}
if(sum>=k)return 1;
else return 0;
}
int main()
{
int n;
int k;
while(~scanf("%d%d",&n,&k))
{
int a[n];
for(int i=0;i<n;i++)
{
double y;
scanf("%lf",&y);
a[i]=y*100;
}
int l=0;
int r=10000009;
int ans;
while(r>=l)
{
int mid=(l+r)/2;
//if(mid==0)break;
if(check(a,n,k,mid))
{
ans=mid;
l=mid+1;
}
else r=mid-1;
}
printf("%.2lf\n",(double)r/100);
}
}
刚开始忘记了多组输入
然后在洛谷提交一次
通过提交过后下载测试点数据的发现了
(r>=l)这个条件比(r>l)精度更加高 就很nice
看来以后刷题都要偷偷再去洛谷交一边可能有额外搜获哦(因为我们学习平台还是没有洛谷专业)
问题 B: 如何放牛()(没有搜题)
描述
农夫有n个牛栏,m头牛,然后要让你把m个牛都放进牛栏里,让两头牛之前的最大的最小距离
格式
输入格式
多组输入
输入n,m (1<=m<=n<=100000)
下面n行是牛栏的位置xi (0 <= xi <= 1,000,000,000)
输出格式
输出两头牛最大的最小距离
样例
样例输入 Copy
5 3
1
2
8
4
9
样例输出 Copy
3
提示
FJ可以将他的3头奶牛放在位置1,4和8的摊位上,最小距离为3.
大量输入数据,建议使用scanf
虽然没有看懂题目 但是看了一下数据
猜测到了这个是求最大化最小值
ac代码
#include<stdio.h>
long a[1000005];
int check(long *a,int n,int m,long ans)//ans为最少距离 m为个数
{
long start=a[0];
long sum=1;
for(int i=1;i<n;i++)
{
if(a[i]-start>=ans)
{
sum++;
start=a[i];
}
}
// printf("sum%d m%ld %ld",sum,m,ans);
// getchar();
if(sum>=m)return 1;
else return 0;
}
int qqsort(long *a,int start,int end)
{
if(start>=end)return 0;
int i=start;
int j=end;
int t=a[start];
while(i<j)
{
while(i<j&&a[j]>t)j--;
if(i<j)a[i++]=a[j];
while(i<j&&a[i]<t)i++;
if(i<j)a[j--]=a[i];
}
a[i]=t;
qqsort(a,start,i-1);
qqsort(a,i+1,end);
}
int main()
{
int m,n;
while(~scanf("%d%d",&n,&m))
{
long r=1000000000;
for(int i=0;i<n;i++)
{
scanf("%ld",a+i);
//if(r<a[i])r=a[i];
}
qqsort(a,0,n-1);
// for(int i=0;i<n;i++)
// printf("%ld ",a[i]);
r++;
long l=0;
while(l<=r)
{
long mid=(r+l)/2;
if(check(a,n,m,mid))
{
l=mid+1;
}
else
{
r=mid-1;
}
}
printf("%ld\n",r);
}
}
小结一下
学习了二分感觉自己又棒棒哒 又多一种暴力求解的思路
还有今天 我不晓得我学多久 但是一定有7小时 早上签到 然后不小心又睡着了 噶!
标签:20,int,mid,long,start,while,2021,end,预备役 来源: https://blog.csdn.net/erxiong111/article/details/112912517