zoukankan      html  css  js  c++  java
  • [POI2013]BAJBytecomputer

    C.[POI2013]BAJ-Bytecomputer

    首先先说猜想:最终序列中所有数都是\(-1,0,1\),且不存在先改后面,后改前面的状态。

    有了这个猜想,就可以DP了。我们设\(f_{i,j}\)表示要使位置\(i\)出现数\(j\),且前\(i\)个位置单调不降的最小费用。则我们枚举往\(a_{i+1}\)上加多少个\(j\)(明显只能加\(0/1/2\)个),判断往\(a_{i+1}\)上加上这么多\(j\)后是否仍满足单调不降,如果可以那就直接转移没问题了。

    下面来讲证明。全是\(-1,0,1\)很好证,因为原本所有数都在此值域内,你要加出这个值域肯定要耗费更多代价。

    不存在先改后面,后改前面的状态也很好证——首先,我们观察到执行a[i]+=a[i-1],肯定有一种方案使得要么它在\(a_{i-1}\)符合要求之前执行,要么它在\(a_{i-1}\)符合要求之后执行。而两次执行,都是\(+1/0/-1\),假如两次相同,那肯定可以看作一端执行两遍;有一个是\(0\),不如不执行;则只剩下一次\(+1\),一次\(-1\)的状况,但这样等价于没执行,所以也可以忽略。

    则上述解法正确。

    代码:

    #include<bits/stdc++.h>
    using namespace std;
    int n,a[1000100],f[1001000][3],res=0x3f3f3f3f;
    int main(){
    	scanf("%d",&n),memset(f,0x3f,sizeof(f));
    	for(int i=1;i<=n;i++)scanf("%d",&a[i]);
    	f[1][a[1]+1]=0;
    	for(int i=1;i<n;i++)for(int j=-1;j<=1;j++)for(int k=0;k<=2;k++)if(a[i+1]+k*j>=j&&a[i+1]+k*j<=1)f[i+1][a[i+1]+k*j+1]=min(f[i+1][a[i+1]+k*j+1],f[i][j+1]+k);
    	for(int i=-1;i<=1;i++)res=min(res,f[n][i+1]);
    	if(res==0x3f3f3f3f)puts("BRAK");else printf("%d\n",res);
    	return 0;
    }
    

  • 相关阅读:
    7. 配置undo表空间
    8. Truncate undo表空间
    品味ZooKeeper之Watcher机制_2
    品味ZooKeeper之纵古观今_1
    《Andrew Ng深度学习》笔记5
    《Andrew Ng深度学习》笔记4
    《Andrew Ng深度学习》笔记3
    《Andrew Ng深度学习》笔记2
    《Andrew Ng深度学习》笔记1
    回归算法
  • 原文地址:https://www.cnblogs.com/Troverld/p/14601195.html
Copyright © 2011-2022 走看看