• Jzoj5408 Dark


    LichKing 希望收集邪恶的黑暗力量,并依靠它称霸世界。
    世间的黑暗力量被描述成一个长度为N 的非负整数序列{Ai},每次它可以选择这个序列中的两个相邻的正整数,让他们的值同时减一并获得一点邪恶力量,直到不存在满足条件的数。

    然而你不希望他能够得逞,所以你会使得他收集的能量尽可能少。

    这个题目存在线性的dp,这里先说一种ΣAi的方法

    我们设f[i][j][0/1]表示现在正在做第i位,这一位为j,前一位是否为0的最优解

    显然我们不能在状态中保留连续的两个非零数

    发现可以如下转移

    f[i][j][0]=min({f[i-1][a[i]-j-k][1]+a[i]-j},f[i-1][a[i]-j][0]+a[i]-j)

    f[i][j][1]=f[a[i]-j][0]+a[i]-j

    这样在加上滚动数组即可

    关于线性方法,我们设f[i]表示处理道第i位,且必须将第i位清零的答案

    那么显然,不管第i位前后是否为0,我们都可以花Ai的代价将其清除(因为这样显然不是最优情况)

    那么我们考虑可以从f[i-2]中转移过来,代价是ai

    因为我们显然可以只讲ai清空而不管ai-1(从f[i-2]转移),也可以考虑清空ai和ai-1(从f[i-1])

    我们还可以考虑从f[i-3]转移过来

    这样必须清空a[i]和a[i-1]而不管a[i-2]

    这样,最后的答案就是f[n+1]

    方法1:code

    #pragma GCC optimize("O3")
    #pragma G++ optimize("O3")
    #include<stdio.h>
    #include<string.h>
    #include<algorithm>
    #define N 5000010
    using namespace std;
    int f[N][2],g[N][2],s[N],a[N],n,A=1<<30;
    inline void gmin(int& x,int y){ x>y?x=y:0; }
    int main(){
    	freopen("dark.in","r",stdin);
    	freopen("dark.out","w",stdout);
    	scanf("%d",&n); 
    	for(int i=1;i<=n;++i) scanf("%d",a+i);
    	memset(f,0x3f,sizeof f); 
    	memset(g,0x3f,sizeof f); 
    	f[0][0]=s[0]=0;
    	for(int i=1;i<=n;++i){
    		for(int j=a[i-1]+1;j<=a[i];++j)
    			f[j][0]=f[j][1]=s[j]=0x3f3f3f3f;
    		for(int j=a[i];~j;--j) g[j][0]=g[j][1]=0x3f3f3f3f;
    		for(int j=a[i];~j;--j){
    			gmin(g[j][0],s[a[i]-j]+a[i]-j);
    			gmin(g[j][0],f[a[i]-j][0]+a[i]-j);
    			gmin(g[j][1],f[a[i]-j][0]+a[i]-j);
    		}
    		s[a[i]+1]=0x3f3f3f3f;
    		for(int j=a[i];~j;--j){
    			f[j][0]=g[j][0];
    			f[j][1]=g[j][1];
    			s[j]=min(s[j+1],f[j][1]);
    		}
    	}
    	A=f[0][0];
    	for(int i=0;i<=a[n];++i) gmin(A,f[i][1]);
    	printf("%d
    ",A);
    }

    线性dp代码:

    #include<bits/stdc++.h>
    using namespace std;
    #define N 100010
    int n,a[N],f[N];
    int input() {
    	int f=1,g=0; char c=getchar();
    	while(c<'0'||c>'9') {if(c=='-')f=-1;c=getchar();}
    	while(c>='0'&&c<='9') {g=(g<<3)+(g<<1)+c-'0';c=getchar();}
    	return f*g;
    }
    int main() {
    	freopen("dark.in","r",stdin);
    	freopen("dark.out","w",stdout);
    	n=input()+3;
    	for(int i=3;i<n;i++) a[i]=input();
    	for(int i=3;i<=n;i++)
    		f[i]=min(f[i-2]+a[i],f[i-3]+max(a[i-1],a[i]));
    	printf("%d
    ",f[n]);
    	return 0;
    }

  • 相关阅读:
    php $_SERVER 中的 QUERY_STRING和REQUEST_URI
    php 弱类型比较
    php函数漏洞
    web源码泄露
    sqlmap 基本使用步骤(一)
    php 调用远程url
    $_POST 和 php://input 的区别
    poj 3461 Oulipo (KMP入门)
    hdu 5417 Victor and Machine
    HDU 1885 Key Task (bfs)
  • 原文地址:https://www.cnblogs.com/Extended-Ash/p/9477235.html
Copyright © 2020-2023  润新知