Focus on yours|

wscqwq

园龄:2年粉丝:2关注:3

A 魔力屏障

A 魔力屏障

我们考虑设 f[i][j][k] 表示击破区间 [i,j] 后,剩余魔力 k,最少需要多少能量。

初始状态:对于所有区间为 [i,i],击破后剩余 a[i]/2,最少需要 a[i]。(如果击破能量超过 a[i]/2,可以发现不是最优的,因为穿过之后会减半,所以尽量还是下次发功)。

转移,考虑先击破 [mid,j],再击破 [i,mid1],那么剩余的能量会相加(如果顺序反一下,可以发现相当于一次性击破整个,待会儿考虑),即 f[i][j][k]=min(f[i][mid1][kp]+f[mid][j][p])p 的取值需要满足 aj/2,因为至少要 aj 才能击穿到达 aj/2 这个),然后再考虑 f[i][j][max(p,ar)/2(穿)]=f[i][j1][p]+max(0,ajp)

发现 k 这一维取到 maxa 即可,这个原因和初始状态设定的原因是一样的。

#include<iostream>
#include<cstring>
using namespace std;
#define Ed for(int i=h[x];~i;i=ne[i])
#define Ls(i,l,r) for(int i=l;i<r;++i)
#define Rs(i,l,r) for(int i=l;i>r;--i)
#define Le(i,l,r) for(int i=l;i<=r;++i)
#define Re(i,l,r) for(int i=l;i>=r;--i)
#define L(i,l) for(int i=0;i<l;++i)
#define E(i,l) for(int i=1;i<=l;++i)
#define W(t) while(t--)
#define Wh while

const int N=75,M=160;
int n,a[N],f[N][N][M],m;
int main(){
	ios::sync_with_stdio(0);
	cin.tie(0);
	cout.tie(0);
	memset(f,0x3f,sizeof f);
	cin>>n;
	E(i, n)cin>>a[i],m=max(m,a[i]);
	E(i, n){
		f[i][i][a[i]>>1]=a[i];
		Le(j, (a[i]>>1)+1, m)f[i][i][j]=j<<1;//可略去
	}
	Le(len, 2, n)
		for(int l=1;l+len-1<=n;++l){
			int r=l+len-1;
			Le(mid, l+1, r){
				Le(p, a[r]>>1, m)
					Le(k, a[r]>>1, p)
						f[l][r][p]=min(f[l][r][p],f[l][mid-1][p-k]+f[mid][r][k]);
			}
			L(p, m+1){
				int nxt=max(p,a[r])>>1;
				f[l][r][nxt]=min(f[l][r][nxt],f[l][r-1][p]+max(0,a[r]-p));
			}
		}
	E(i, n){
		int ret=1e9;
		Le(k, a[i]>>1, m)
			ret=min(ret,f[1][i][k]);
		cout<<ret<<' ';
	}
	return 0;
}

本文作者:wscqwq

本文链接:https://www.cnblogs.com/wscqwq/p/17771321.html

版权声明:本作品采用知识共享署名-非商业性使用-禁止演绎 2.5 中国大陆许可协议进行许可。

posted @   wscqwq  阅读(17)  评论(0编辑  收藏  举报
点击右上角即可分享
微信分享提示
评论
收藏
关注
推荐
深色
回顶
收起