题解:CF2169E Points Selection
本题体现了非法情况不优,则可以不管非法情况的思想,该思想可以用这道例题入门。为了便于不了解该思想的选手阅读题解,本题解先讲做法,再说正确性。
做法
按照题意,保留的点下标组成集合
反过来考虑每个点对答案的贡献,发现贡献可能是:
还有别的可能吗?再仔细一想,如果一个点作为保留点的最右下角,其贡献是
还有什么限制?我们发现在计算周长时,
参考代码:
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
ll t,n,xx[300010],yy[300010],c[300010],dp[300010][16];
int main(){
std::ios::sync_with_stdio(false);
cin.tie(0);
cin>>t;
while(t--){
cin>>n;
for(int i=1;i<=n;i++) cin>>xx[i];
for(int i=1;i<=n;i++) cin>>yy[i];
for(int i=1;i<=n;i++) cin>>c[i];
for(int i=0;i<=n+5;i++){
for(int j=0;j<16;j++) dp[i][j]=-1e18;
}
dp[0][0]=0;
for(int i=0;i<=n-1;i++){
for(int j=0;j<16;j++){
for(int k=0;k<16;k++){
if(k&j) continue;
ll tmp=0;
if(k&(1<<0)) tmp+=2*xx[i+1];
if(k&(1<<1)) tmp-=2*xx[i+1];
if(k&(1<<2)) tmp+=2*yy[i+1];
if(k&(1<<3)) tmp-=2*yy[i+1];
if(!k) tmp=c[i+1];
dp[i+1][j|k]=max(dp[i+1][j|k],dp[i][j]+tmp);
}
}
}
cout<<dp[n][15]<<"\n";
}
return 0;
}
正确性
刚刚的 DP 有一些看上去显而易见的问题:
DP 里只确保了
答:这就是我们提到的“非法情况不优,则可以不管非法情况”思想,即如果
类似的,DP 中会考虑包括三项的贡献式子也是如果非法一定不优的、所以可以考虑。