掌中之物,未必在掌握之中。|

2021hych

园龄:2年7个月粉丝:2关注:2

P3558 [POI2013]BAJ-Bytecomputer题解

题型考察

此题是经典的最优解问题,考虑贪心或 DP 解决。贪心似乎不可行,因此考虑 DP

在序列上首先考虑线性 DP

思路

首先按照常规思路,DP 的第一个维度表示当前到第几个数,即 dp[i] 表示 a[1i] 的最优解。接下来考虑其他维度,在转移过程中无论是从哪转移还是转移到哪里,都是和 a 数组的值相关,考虑第二维度表示当前位置的数值在三种情况下分别的最优解。因此状态设计更新为 dp[i][j] 表示 a[1i]a[i]=j+1 的最优解。(加一是为了避免负数下标)。此时状态设计结束。

处理边界值,作为数组的第一个数,无论怎么对数组中的数字进行操作,a[1] 的值始终不变,故有:

dp[1][0]=dp[1][1]=dp[1][2]=inf;
dp[1][a[1]+1]=0;

inf 是大常数,起到无穷大的作用。此刻初始化结束。

考虑状态转移方程。作为 DP 的核心,通常要在不同的条件下明确由谁到谁的转移。一般化的,当前要转移得到的对象为 dp[i][j]

a[i]=1

//cmin(a,b,c)=min(a,min(b,c))
dp[i][0]=dp[i-1][0];//不需要有转移代价+遵循单调不降(dp[i][1]与dp[i][2]便不参与本次转移)
if(a[i-1]==1) dp[i][1]=min(dp[i-1][0],dp[i-1][1])+1;//此时转移代价为1次+遵循单调不降(dp[i][2]便不参与本次转移)
else dp[i][1]=inf;//此时无法转移
if(a[i-1]==1) dp[i][2]=cmin(dp[i-1][0],dp[i-1][1],dp[i-1][2])+2;//此时转移代价为2次+遵循单调不降(统统参与本次转移)
else dp[i][2]=dp[i-1][2]+2;//此时转移代价为2次+遵循单调不降(特殊条件,dp[i][0]与dp[i][1]便不参与本次转移)

按照此思路,同理可得。
a[i]=0

dp[i][0]=dp[i-1][0]+1;
dp[i][1]=min(dp[i-1][0],dp[i-1][1]);
if(a[i-1]==1) dp[i][2]=cmin(dp[i-1][0],dp[i-1][1],dp[i-1][2])+1;
else dp[i][2]=dp[i-1][2]+1;

a[i]=1

dp[i][0]=dp[i-1][0]+2;
if(a[i-1]==-1) dp[i][1]=min(dp[i-1][0],dp[i-1][1])+1;
else dp[i][1]=dp[i-1][0]+1;
dp[i][2]=cmin(dp[i-1][0],dp[i-1][1],dp[i-1][2]);

此刻状态转移方程结束。

目标状态,对于此题,可以发现答案为

ans=cmin(dp[n][0],dp[n][1],dp[n][2]);

另外如果 ans 大于等于 inf 就输出 BRAK

代码实现

#include<bits/stdc++.h>
#define int long long
using namespace std;
const int N=1000010;
const int inf=1e9;
int n,ans;
int a[N],dp[N][3];
int cmin(int x,int y,int z) {
	return min(x,min(y,z));
}
signed main() {
	ios::sync_with_stdio(false);
	cin.tie(0);
	cout.tie(0);
	cin>>n;
	for(int i=1;i<=n;i++) cin>>a[i];
	dp[1][0]=dp[1][1]=dp[1][2]=inf;
	dp[1][a[1]+1]=0;
	for(int i=2;i<=n;i++) {
		if(a[i]==-1) {
			dp[i][0]=dp[i-1][0];
			if(a[i-1]==1) dp[i][1]=min(dp[i-1][0],dp[i-1][1])+1;
			else dp[i][1]=inf;
			if(a[i-1]==1) dp[i][2]=cmin(dp[i-1][0],dp[i-1][1],dp[i-1][2])+2;
			else dp[i][2]=dp[i-1][2]+2;
		}
		else if(a[i]==0) {
			dp[i][0]=dp[i-1][0]+1;
			dp[i][1]=min(dp[i-1][0],dp[i-1][1]);
			if(a[i-1]==1) dp[i][2]=cmin(dp[i-1][0],dp[i-1][1],dp[i-1][2])+1;
			else dp[i][2]=dp[i-1][2]+1;
		}
		else {
			dp[i][0]=dp[i-1][0]+2;
			if(a[i-1]==-1) dp[i][1]=min(dp[i-1][0],dp[i-1][1])+1;
			else dp[i][1]=dp[i-1][0]+1;
			dp[i][2]=cmin(dp[i-1][0],dp[i-1][1],dp[i-1][2]);
		}
	}
	ans=cmin(dp[n][0],dp[n][1],dp[n][2]);
	if(ans>=inf) cout<<"BRAK";
	else cout<<ans;
	return 0;
}

本文作者:2021hych

本文链接:https://www.cnblogs.com/2021hych/p/16500211.html

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

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