BZOJ4509 Angry Cows(dp)
题意:
大概就是一条线上有n个炸弹,然后让你随意扔一个爆炸半径为r的炸弹使他们全部爆炸,
第一次被引爆的炸弹爆炸半径为r-1,第二次为r-2。。。
求r最小是多少
思路:
用两个数组处理得到从左往右和从右往左到当前炸弹时的爆炸半径最小是多少,然后枚举投弹位置就可以了
/* *********************************************** Author :devil ************************************************ */ #include <cstdio> #include <cstring> #include <iostream> #include <algorithm> #include <vector> #include <queue> #include <set> #include <map> #include <string> #include <cmath> #include <stdlib.h> using namespace std; typedef long long LL; const int inf=0x3f3f3f3f; const int mod=1e9+7; const int N=5e4+10; int ml[N],mr[N],a[N],n; int main() { //freopen("in.txt","r",stdin); scanf("%d",&n); for(int i=1;i<=n;i++) scanf("%d",&a[i]); sort(a+1,a+n+1); memset(ml,inf,sizeof(ml)); memset(mr,inf,sizeof(mr)); ml[1]=mr[n]=0; int k=1; for(int i=2;i<=n;i++) { while(k+1<i&&a[i]-a[k+1]>ml[k+1]+1) k++; ml[i]=min(a[i]-a[k],ml[k+1]+1); } k=n; for(int i=n-1;i>=1;i--) { while(k-1>i&&a[k-1]-a[i]>mr[k-1]+1) k--; mr[i]=min(a[k]-a[i],mr[k-1]+1); } double ans=inf; for(int i=1,j=n;i<j;) { ans=min(ans,(double)max((a[j]-a[i])/2.0,(double)max(ml[i],mr[j])+1)); if(ml[i+1]<mr[j-1]) i++; else j--; } printf("%.1f\n",ans); return 0; }