解法1:BFS。需要一点剪枝,用一个vis[i][j](表示位置走到下标为i的点用了j步)数组存下当前状态的最大值,只有大于这个值才入列。
#include<iostream>
#include<queue>
#include<algorithm>
#include<cstring>
using namespace std;
const int N=150;
int a[N],vis[N][N];
int n,aa,bb,k,ans;
struct node{
int w,step,sum;
};
void bfs(){
node st;
st.w=1;
st.sum=a[1];
st.step=0;
queue<node>q;
q.push(st);
while(!q.empty()){
node ne;
st=q.front();
q.pop();
if(st.w>n||st.step==k){
ans=max(ans,st.sum);
continue;
}
for(int i=aa;i<=bb;i++){
ne.w=st.w+i;
ne.sum=st.sum+a[ne.w];
ne.step=st.step+1;
if(ne.sum>vis[ne.w][ne.step]){//剪枝
q.push(ne);
vis[ne.w][ne.step]=ne.sum;
}
}
}
}
int main(){
int t;
cin>>t;
while(t--){
memset(a,0,sizeof(a));
memset(vis,0,sizeof(vis));
cin>>n>>aa>>bb>>k;
for(int i=1;i<=n;i++) cin>>a[i];
ans=0;
bfs();
cout<<ans<<endl;
}
return 0;
}
解法2:dp
题记:实际上题目的数据a[]是递增的(题目没说)所以每次都必定走到n点,所以我们用f[i][j]表示青蛙跳j次到达i位置最多可以吃到的昆虫,最后输出f[n][k]也能ac。
#include<iostream>
#include<cstdio>
#include<algorithm>
#include<cstring>
using namespace std;
const int N=110;
int a[N],f[N][N];
int main(){
int t;
scanf("%d",&t);
while(t--){
int n,aa,bb,k;
memset(f,0,sizeof(f));
scanf("%d%d%d%d",&n,&aa,&bb,&k);
for(int i=1;i<=n;i++) scanf("%d",&a[i]);
f[0][1]=a[1];
for(int i=1;i<=n;i++){
for(int j=1;j<=k;j++)
for(int l=i+aa;l<=i+bb&&l<=n;l++)
f[l][j]=max(f[l][j],f[i][j-1]+a[l]);
}
cout<<f[n][k]+a[1]<<endl;
}
return 0;
}