其他分享
首页 > 其他分享> > 预备役总结2021年1月20日

预备役总结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