题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=5248
解题思路:这道题我原本的思路是动态规划,结果看到数很大,结果放弃了。然后想到二分,思路是对的,只是在check()函数时想的太复杂了,没有想到这里有贪心的结构,而采用的是动规去枚举。结果超时了。假设二分枚举到x,那么a[i]就可以尽可能地变小,最小可以小到a[i]-x,这样就可以把数列变成尽可能小的递增序列。感觉对有些题的贪心结构还是不敏感。
#include<iostream>
#include<cstdio>
#include<cstring>
using namespace std;
const int maxn = 100005;
int n,A[maxn],B[maxn];
bool check(int len)
{
for(int i = 1; i <= n; i++)
B[i] = A[i];
B[1] = B[1] - len;
for(int i = 2; i <= n; i++)
{
if(B[i] <= B[i-1])
{
if(B[i-1] + 1 - B[i] <= len) B[i] = B[i-1] + 1;
else return false;
}
else if(B[i] - B[i-1] > len) B[i] = B[i] - len;
else B[i] = B[i-1] + 1;
}
return true;
}
int main()
{
int t,cas = 1;
scanf("%d",&t);
while(t--)
{
scanf("%d",&n);
for(int i = 1; i <= n; i++)
scanf("%d",&A[i]);
int l = 0,r = 1000000,mid,ans = 0;
while(l <= r)
{
mid = (l + r) >> 1;
if(check(mid) == true)
{
ans = mid;
r = mid - 1;
}
else l = mid + 1;
}
printf("Case #%d:\n%d\n",cas++,ans);
}
return 0;
}