2E 求hack(非正解)
查看原帖
2E 求hack(非正解)
320423
s4CRIF1CbUbbL3AtIAly楼主2023/7/24 01:18

我知道正解是反悔贪心,但是我不知道为什么我的dp是错误的

#include<bits/stdc++.h>
using namespace std;
#define int long long
#define x first
#define y second
int n,k;
int a[200005];
int d[200005];
pair<int,int> f[200005][2];//0:no 1:+k 2:-k
signed main(){int _;cin>>_;while(_--){
	cin>>n>>k;
	for(int i=1;i<=n;i++) cin>>a[i],(a[i]==k?a[i]=0:0);
	for(int i=1;i<=n;i++) d[i]=a[i-1]-a[i];
	d[n+1]=a[n];
	for(int i=0;i<2;i++) f[0][i].x=d[1],f[0][i].y=abs(d[1]);
	for(int i=1;i<=n;i++){
		for(int j=0;j<2;j++){
			int mn=0x3f3f3f3f3f3f3f3fll,K=2;
			for(int L=0;L<2;L++){
				if(f[i-1][L].y-abs(f[i-1][L].x)+abs(f[i-1][L].x-(j==0?0:k))+abs(d[i+1]+(j==0?0:k))<mn){
					mn=f[i-1][L].y-abs(f[i-1][L].x)+abs(f[i-1][L].x-(j==0?0:k))+abs(d[i+1]+(j==0?0:k));
					K=L;
				}
			}
			f[i][j]={d[i+1]+(j==0?0:k),mn};
		}
	}
	cout<<(min(f[n][0].y,f[n][1].y)+1)/2<<endl;
}return 0;}

大致思路:显然在达到0就死亡不能再打的情况下答案是差分数组的绝对值之和再 +1 再 /2,然后考虑每一次把一个血量上移 kk 与题目要求等价,其对差分数组的影响就是前面 −k-k 后面 +k+k,然后直接 dp 算加或不加,最后取最小值

求 hack

2023/7/24 01:18
加载中...