hihocoder 193周 修补木桶

 1 /*
 2   Source   :hihocoder193周 修补木桶
 3   Problem  :一个圆形的木桶由n块木板围成,可以使用一种操作把连续的一段长度为L的区间中的木板变成无限长,操作可以使用m次,问最终最短的木板是多长。n<=1000,L<=20,m*L<n
 4   Solution :直接计算较为困难,考虑一个简单一点的问题:如果知道了最终最短木板的长度,那么把这n块木板变成满足条件的最小操作次数是多少次。如果是一个序列,那么我们可以从
 5             第一个位置贪心的枚举,这样可以求得最终需要的次数。对于一个环,拆成n条链分别判断。
 6             其次,我们可以发现随着最终最短木板长度的增加,需要的操作次数是递减的。于是可以二分最终最短木板的长度。
 7   Date     :2018-08-16-15.32
 8 */
 9 
10 #include <bits/stdc++.h>
11 using namespace std;
12 
13 typedef long long LL;
14 const int MAXN = 100005;
15 const LL MOD7 = 1e9+7;
16 
17 int a[2005];
18 int ans[1005];
19 int n,m,Len;
20 
21 
22 bool check(int x)
23 {
24     for (int i=1;i<=Len;++i)
25     {
26         int t=0;
27         for (int j=i;j<i+n;++j)
28         {
29             if (a[j]<x)
30             {
31                 ++t;
32                 j+=Len-1;
33             }
34         }
35         if (t<=m) return true;
36     }
37     return false;
38 }
39 
40 int main()
41 {
42 #ifndef ONLINE_JUDGE
43     freopen("test.txt","r",stdin);
44 #endif // ONLINE_JUDGE
45     scanf("%d%d%d",&n,&m,&Len);
46     {
47         for (int i=1;i<=n;++i)
48         {
49             scanf("%d",&a[i]);
50             ans[i]=a[i];
51         }
52         for (int i=1;i<=n;++i) a[n+i] = a[i];
53         sort(ans+1,ans+1+n);
54         int l=1,r=n;
55         int mid;
56         while (l<=r)
57         {
58             mid=(l+r)/2;
59             // printf("l=%d r=%d mid=%d check(%d)=%d\n",l,r,mid,ans[mid],check(ans[mid]));
60             if (check(ans[mid])) l=mid+1;
61             else r=mid-1;
62         }
63         printf("%d\n",ans[l-1]);
64     }
65     return 0;
66 }

 

posted @ 2018-08-16 20:40  LeeSongt  阅读(151)  评论(0编辑  收藏  举报