题解 P3957 【跳房子】
Jμdge
2018-03-29 13:26:49
忽然感觉楼下大佬们的题解好复杂的样子(还有90分过不了的),然后我就发一个分分钟能过的朴素算法好了(~~而且超朴素的样子什么优化都去见鬼好了~~):
```cpp
#include<bits/stdc++.h>
typedef long long ll;
#define M 500005
using namespace std;
ll n,d,k,l,r=1005; //这里你可以改成1e5+5试一下,照样AC!
ll ans=-1;
ll far[M],val[M],f[M];
ll read()
{
char c=getchar(); ll x=0,f=1;
while(!isdigit(c) && c!='-') c=getchar();
if(c=='-') { f=-1; c=getchar(); }
while(isdigit(c)) { x=(x<<3)+(x<<1)+c-'0'; c=getchar(); }
return x*f;
}
bool check(ll g)
//这里就体现了朴素啊。。什么单调优化双端队列之类的都去见鬼好了
{
memset(f,128,sizeof(f));f[0]=0;
for(int i=0;i<n;++i) //就是个二维,没见的爆了啊?嗯哈?
//因为循环里还有剪枝的啊你这么担心爆爆爆的干啥?
//朴素点不好去整些优化啥的还爆了?(对自己说的)
for(int j=i+1;j<=n;++j)
{
if(far[j]-far[i]>d+g) break;
if(far[j]-far[i]<max(d-g , (ll)1)) continue;
f[j]=max(f[j] , f[i]+val[j]);
if(f[j]>=k) return true;
}
return false;
}
int main() //主程序还是挺简洁的,差不多就一个读入和二分查找
{
n=read(); d=read(); k=read();
for(int i=1;i<=n;++i)
{ far[i]=read(); val[i]=read(); }
ll mid;
while(l<=r)
{
mid=(l+r)>>1;
check(mid)? ans=mid,r=mid-1 : l=mid+1;
}
printf("%lld\n",ans);
return 0;
}
```
然后我算了一下,如果说是二分1e5的话,常数大概就是log(1e5)=17 了,这难道还不省啊?~~再加上数据也不会坑到说让你整个二重循环走一遍~~,所以。。。。所以。。。。就这样了啊!O( < 17*1e10 ) 的算法还是过了~~~~~~~~~~