[NOIp2010] luogu P1541 乌龟棋

英语老师讲 mind map,真想说一句“声微饭否”。为什么wyy的歌词总是快一点点。在报csp。

题目描述

你在一个序列上向正方向行走,起点是 a [ 0 ] a[0] a[0]。每一步可以走 1 , 2 , 3 , 4 1,2,3,4 1,2,3,4 格,每种步长的使用次数受限,保证用完步数后恰好到达终点。一次行走的得分为经过所有点的权值之和。求最大得分。

Solution

看这个数据范围就知道是 DP 了。
f [ i ] [ j ] [ k ] [ l ] f[i][j][k][l] f[i][j][k][l] 表示使用 i , j , k , l i,j,k,l i,j,k,l 1 , 2 , 3 , 4 1,2,3,4 1,2,3,4 步的最大得分。显然你现在的位置是 s u m = i + 2 j + 3 k + 4 l sum=i+2j+3k+4l sum=i+2j+3k+4l注意特判起点。时间复杂度 O ( M 4 ) O(M^4) O(M4),空间复杂度 O ( M 4 ) O(M^4) O(M4)

#include<cstdio>
#include<cstdlib>
#include<cstring>

const int MAXN=45;

int n,m;
int g[5]={0,0,0,0,0},a[400];
int sx;
int f[MAXN][MAXN][MAXN][MAXN];

int max(int x,int y){
	return x>y?x:y;
}
int sum(int a,int b,int c,int d){
	return a+b+b+c+c+c+d+d+d+d+1;
}
int main(){
	scanf("%d%d",&n,&m);
	for(int i=1;i<=n;++i)
		scanf("%d",&a[i]);
	for(int i=1;i<=m;++i){
		scanf("%d",&sx);
		++g[sx];
	}
	memset(f,0,sizeof(f));f[0][0][0][0]=a[1];
	for(int i=0;i<=g[1];++i)
		for(int j=0;j<=g[2];++j)
			for(int k=0;k<=g[3];++k)
				for(int l=0;l<=g[4];++l){
					//这里我打得比较丑
					if(i)
						f[i][j][k][l]=max(f[i][j][k][l],f[i-1][j][k][l]+a[sum(i,j,k,l)]);
					if(j)
						f[i][j][k][l]=max(f[i][j][k][l],f[i][j-1][k][l]+a[sum(i,j,k,l)]);
					if(k)
						f[i][j][k][l]=max(f[i][j][k][l],f[i][j][k-1][l]+a[sum(i,j,k,l)]);
					if(l)
						f[i][j][k][l]=max(f[i][j][k][l],f[i][j][k][l-1]+a[sum(i,j,k,l)]);
				}
	printf("%d",f[g[1]][g[2]][g[3]][g[4]]);
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值