我知道正解是反悔贪心,但是我不知道为什么我的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,然后考虑每一次把一个血量上移 k 与题目要求等价,其对差分数组的影响就是前面 −k 后面 +k,然后直接 dp 算加或不加,最后取最小值
求 hack