POI2013 Bytecomputer

题目:http://www.lydsy.com/JudgeOnline/problem.php?id=3427

可以证明最终序列为-1...0....1

因为首先如果 a(i-1) 为-1或0,执行操作不会让答案变优。

然后,如果可以加到大于1的某个数字,一定可以加到1,显然加到1更佳。

然后简单dp,f[i][j]表示第i位为j的最少步数。

#include <cstdio>
#include <cstring>
#include <algorithm>

#define N 1000010

using namespace std;

int f[N][3],n,a[N];

int min(int a,int b,int c,int d){
    return min(min(a,d),min(b,c));
}

int min(int a,int b,int c){
    return min(a,min(b,c));
}

int calc(int x,int to,int v){
    v--;
    if(x==to) return 0;
    if(x+v==to) return 1;
    if(x+2*v==to) return 2;
    return 0x3f3f3f3f;
}

int main(){
    memset(f,0x3f,sizeof(f));
    scanf("%d",&n);
    for(int i=1;i<=n;i++) scanf("%d",&a[i]),a[i]++;
    f[1][a[1]]=0;
    for(int i=2,s1,s2;i<=n;i++){
        f[i][0]=min(f[i][0],f[i-1][0]+calc(a[i],0,0));
        f[i][1]=min(f[i][1],f[i-1][1]+calc(a[i],1,1),f[i-1][0]+calc(a[i],1,0));
        f[i][2]=min(f[i][2],f[i-1][2]+calc(a[i],2,2),f[i-1][1]+calc(a[i],2,1),f[i-1][0]+calc(a[i],2,0));
    }
    int ans=min(f[n][0],f[n][1],f[n][2]);
    if(ans>=0x3f3f3f3f) puts("BRAK");
    else printf("%d\n",ans);
    return 0;
}
View Code

 

posted @ 2015-06-04 08:20  lawyer'  阅读(164)  评论(0编辑  收藏  举报