【ural 1223】 Chernobyl' Eagle on a Roof 题解
URAL-1223 Chernobyl’ Eagle on a Roof 题解
详细的题解、dp优化的个人理解和解释可以见我的这一篇文章
本文仅用于存放AC的代码以供参考。
O(k*n^2) 无优化dp
#include <cstdio>
#include <algorithm>
#include <cstring>
using namespace std;
typedef long long ll;
#define REG register
#define rep(i,a,b) for(REG int i=a;i<=b;i++)
#define Rep(i,a,b) for(REG int i=a;i>=b;i--)
const int INF=1e9;
int N,K,f[20][1010];
inline int log2(int x){
int l=1,r=x,c=0;
while(l<=r){
int mid=(l+r)>>1; c++;
if(r-mid>mid-l) l=mid+1;
else r=mid-1;
}
return c;
}
int main(){
while(1){
scanf("%d%d",&K,&N);
if(K==N&&K==0) break;
if(K>log2(N)){
printf("%d\n",log2(N)); continue;
}
memset(f,0,sizeof(f));
rep(i,1,N) f[1][i]=i;
rep(i,2,K){
rep(j,1,N){
f[i][j]=INF;
rep(w,1,j)
f[i][j]=min(f[i][j],max(f[i-1][w-1],f[i][j-w])+1);
}
}
printf("%d\n",f[K][N]);
}
return 0;
}
O(KNlogN) 二分优化dp
#include <cstdio>
#include <cstring>
#include <algorithm>
using namespace std;
const int INF=1e9,K=20,N=1010;
inline int log2(int x){
int l=1,r=x,c=0;
while(l<=r){
int mid=(l+r)>>1; c++;
if(r-mid>mid-l) l=mid+1;
else r=mid-1;
}
return c;
}
int k,n,a[2][N];
int main(){
while(scanf("%d%d",&k,&n)==2){
if(k+n==0) break;
int t=log2(n);
if(k>=t){
printf("%d\n",t);
continue;
}
int *p=a[0],*f=a[1];
for(int i=1;i<=n;i++) f[i]=i;
for(int i=2;i<=k;i++){
swap(p,f);
for(int j=1;j<=n;j++) f[j]=0;
f[1]=1;
for(int j=2;j<=n;j++){
t=log2(j);
if(i>=t){ f[j]=t; continue; }
int l=1,r=j,mid,ans=r;
while(l<=r){
mid=(l+r)>>1;
if(p[mid-1]>=f[j-mid]) ans=mid,r=mid-1;
else l=mid+1;
}
f[j]=max(p[ans-1],f[j-ans])+1;
if(--ans>=1) f[j]=min(f[j],max(p[ans-1],f[j-ans])+1);
}
}
printf("%d\n",f[n]);
}
return 0;
}
O(KN)线性优化
这里是没有开long long的必要的,但是我懒得改了。
#include <cstdio>
#include <algorithm>
#include <vector>
using namespace std;
typedef long long ll;
inline ll log2(ll x){
ll l=1,r=x,c=0;
while(l<=r){
ll mid=(l+r)>>1; c++;
if(r-mid>mid-l) l=mid+1;
else r=mid-1;
}
return c;
}
vector<ll> f,p;
int main(){
while(1){
ll k,n; scanf("%lld%lld",&k,&n);
if(k+n==0) break;
if(k>=log2(n)){ printf("%lld\n",log2(n)); continue; }
f.resize(n+1);
for(ll i=1;i<=n;i++) f[i]=i;
for(ll i=2;i<=k;i++){
f.swap(p); f.resize(n+1);
ll pre=0; f[1]=1;
for(ll j=2;j<=n;j++){
if(max(f[pre],p[j-pre-1])+1==f[j-1]) f[j]=f[j-1];
else f[j]=f[j-1]+1,pre=j-1;
}
}
printf("%lld\n",f[n]);
}
return 0;
}
可以过1e18大数据的算法
#include <cstdio>
#include <cmath>
using namespace std;
typedef long long ll;
#define REG register
#define rep(i,a,b) for(REG int i=a;i<=b;i++)
#define Rep(i,a,b) for(REG int i=a;i>=b;i--)
inline char getc(){
static char buf[1<<14],*p1=buf,*p2=buf;
return p1==p2&&(p2=(p1=buf)+fread(buf,1,1<<14,stdin),p1==p2)?EOF:*p1++;
}
inline ll scan(){
REG ll x=0; REG char ch=0;
while(ch<48) ch=getc();
while(ch>=48) x=x*10+ch-48,ch=getc();
return x;
}
inline ll log2(ll x){
ll l=1,r=x,mid,c=0;
while(l<=r){
mid=(l+r)>>1; c++;
if(mid-l>r-mid) r=mid-1;
else l=mid+1;
}
return c;
}
const ll F=2e6,K=60,N=1e18;
ll f[K+1][F],end[K+1];
inline void prework(){
rep(i,1,F-200) f[1][i]=i;
rep(i,1,F-200){
rep(j,2,K){
if(end[j]) break;
f[j][i]=f[j][i-1]+f[j-1][i-1]+1;
if(f[j][i]>=N) end[j]=i;
}
}
}
int main(){
//REG int T=scan();
prework();
while(1){
REG ll k=scan(),n=scan(),temp;
if(n+k==0) break;
if(k==1){ printf("%lld\n",n); continue; }
if(k==2){
ll t=floor(sqrt(n<<1));
if(t*(t+1)<n<<1) t++;
printf("%lld\n",t); continue;
}
temp=log2(n);
if(k>=temp){ printf("%lld\n",temp); continue; }
REG int l=1,r=end[k],mid,ans;
while(l<=r){
mid=(l+r)>>1;
if(f[k][mid]>=n) r=mid-1,ans=mid;
else l=mid+1;
}
printf("%d\n",ans);
}
return 0;
}