标签:lse 枚举 class can scanf ring cpp names 记忆
写完这场acm模拟赛去看题解,发现自己这道题的写法跟标程不一样就发出来。标程是组合数的,但是我用记忆化搜索水过去了。
定义状态状态f[two][_two][one][_one]
,表示左脚还要走two次2步长,one次1步长,右脚还要走_two次2步长,_one次1步长。然后每次枚举two和one进行记忆化搜索。
#include<cstdio>
#include<cstring>
#define LL long long
using namespace std;
LL f[51][51][51][51],ans[51];
int tot,two,_two,one,_one;
LL dfs(int a){
if(a==tot) return 1;
LL ans=0;
if(~f[two][_two][one][_one]) return f[two][_two][one][_one];
if(a%2){
if(two){
two--;
ans+=dfs(a+1);
two++;
}
if(one){
one--;
ans+=dfs(a+1);
one++;
}
}else{
if(_two){
_two--;
ans+=dfs(a+1);
_two++;
}
if(_one){
_one--;
ans+=dfs(a+1);
_one++;
}
}
return f[two][_two][one][_one]=ans;
}
int main(){
memset(f,-1,sizeof f);
for(int n=2;n<=50;++n){
LL answ=0;
for(int i=1;i<=n/2;++i){
if(n-i*2<=i){
two=_two=i;
one=_one=n-i*2;
tot=two*2+one*2;
answ+=dfs(1);
}
}
ans[n]=answ;
}
int t,a;
for(scanf("%d",&t);t;--t){
scanf("%d",&a);
printf("%d ",a);
scanf("%d",&a);
printf("%lld\n",ans[a/2]);
}
return 0;
}
跑的飞快。
后来闲着没事打了个表。
#include<cstdio>
using namespace std;
const long long ans[51]={0,0,1,4,1,9,37,16,101,425,226,1261,5342,3185,16661,70624,45397,227925,964702,654589,3192707,13483514,9533591,45499169,191695011,140024274,656975671,2761415749,2071251366,9585067029,40197719157,30823385424,141022545077,590174378453,461076613802,2089303926185,8726567622555,6928035002534,31135655962227,129811259033521,104507122669576,466323616692283,1940942711798053,1581897746416066,7014487515180361,29150498233064655,24018140388709152,105912301155194501,439511434241632076,365668377576409175,1604517292705494701};
int main(){
int t,a;
for(scanf("%d",&t);t;--t){
scanf("%d",&a);
printf("%d ",a);
scanf("%d",&a);
printf("%lld\n",ans[a/2]);
}
return 0;
}
标签:lse 枚举 class can scanf ring cpp names 记忆
原文地址:https://www.cnblogs.com/jiaangk/p/9313251.html