您的位置:首页 > 其它

POJ 1037 DP

2013-07-23 18:31 274 查看
题目链接: http://poj.org/problem?id=1037

分析: 很有分量的一道DP题!!!

(参考于:http://blog.csdn.net/sj13051180/article/details/6669737 )

#include <iostream>
#include <cstdio>
#include <cmath>
#include <cstdlib>
#include <string>
#include <cstring>
#include <algorithm>
#include <iomanip>
using namespace std;

long long up[25][25];
long long down[25][25];
long long ans[25];

void getfirst(long long n,long long c,bool u){
if(n==0) return ;
long long sum=0,t;
if(!u) { //前一步是up,当前步要down
t=ans[n+1];
while(sum+down
[t]<c)
sum+=down
[t++];
} else { //前一步是down,当前步要up
t=1;
while(sum+up
[t]<c)
sum+=up
[t++];
}
ans
=t;  //定位
getfirst(n-1,c-sum,!u);  //搜索下一位
for(int i=1;i<n;++i)
if(ans[i]>=t) ++ans[i];
}

void Init(){
up[1][1]=down[1][1]=1;
for(int i=2; i<=20; ++i)
for(int j=1; j<=i; ++j) {
up[i][j]=down[i][j]=0;
for(int k=j; k<=i-1; ++k)
up[i][j]+=down[i-1][k];
for(int k=1; k<=j-1; ++k)
down[i][j]+=up[i-1][k];
}
}
int main(){
Init();
int T; scanf("%d",&T);
while(T--){
long long c,n;
scanf("%lld%lld",&n,&c);

long long sum=0,t=1;
while(sum+up
[t]+down
[t]<c){
sum+=up
[t]+down
[t];
++t;
}
ans
=t;  //定位首位
//搜索下一位
if(sum+down
[t]<c)                      //在up中
getfirst(n-1,c-sum-down
[t],false);
else                                      //在down中
getfirst(n-1,c-sum,true);
for(int i=1;i<n;++i)// 比如当n=5时, 第一个选了t=3, 还有1,2,4,5 后面会对应到1,2,3,4, 大于t的都相对-1, 最终要+1
if(ans[i]>=t) ++ans[i];

printf("%lld",ans
);
for(int i=n-1;i>=1;--i)
printf(" %lld",ans[i]);
puts("");
}
return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: