• 【BZOJ1802】[AHOI2009]checker(动态规划)


    【BZOJ1802】[AHOI2009]checker(动态规划)

    题面

    BZOJ
    洛谷

    题解

    首先自己观察一波,发现如果有相邻两个格子都是红色的话,那么显然可以在任意位置都存在一个跳棋。可以让两个位置反复互相跳就好了。这样子第一问的答案显然就是(0),否则的话第一问的答案就是偶数位置上(0)的个数。
    如果没有相邻的两个位置都是红格子,我们还可以得出第二问的答案就是偶数位置上红格子的数目。
    现在有两个红格子相邻,设(f[i])表示在(i)这个位置要出现一个棋子的最小加入的跳棋数目,显然可以暴力(dp)。那么最终的答案就是所有偶数位置上的(f)的和。

    #include<iostream>
    #include<cstdio>
    #include<cstdlib>
    #include<cstring>
    #include<cmath>
    #include<algorithm>
    #include<vector>
    using namespace std;
    #define ll long long
    #define MAX 1010
    inline int read()
    {
    	int x=0;bool t=false;char ch=getchar();
    	while((ch<'0'||ch>'9')&&ch!='-')ch=getchar();
    	if(ch=='-')t=true,ch=getchar();
    	while(ch<='9'&&ch>='0')x=x*10+ch-48,ch=getchar();
    	return t?-x:x;
    }
    int n,a[MAX];ll f[MAX];bool fl;
    int main()
    {
    	n=read();
    	for(int i=1;i<=n;++i)a[i]=read();
    	for(int i=3;i<=n;++i)
    		if(a[i]&&a[i-1])fl=true;
    	if(!fl)
    	{
    		int s[2]={0,0};
    		for(int i=2;i<=n;i+=2)s[a[i]]+=1;
    		printf("%d
    %d
    ",s[0],s[1]);
    		return 0;
    	}
    	puts("0");memset(f,63,sizeof(f));
    	for(int i=2;i<=n;++i)if(a[i])f[i]=1;
    	for(int i=2;i<n;++i)
    		if(a[i]&&a[i+1])
    		{
    			for(int j=i-1;j>1;--j)f[j]=min(f[j],f[j+1]+f[j+2]);
    			for(int j=i+2;j<=n;++j)f[j]=min(f[j],f[j-1]+f[j-2]);
    		}
    	ll ans=0;
    	for(int i=2;i<=n;i+=2)ans+=f[i];
    	printf("%lld
    ",ans);
    	return 0;
    }
    
  • 相关阅读:
    绍一集训Round#2
    CF 799B T-shirt buying
    Luogu P2827 蚯蚓
    Luogu P4053 [JSOI2007]建筑抢修
    【LGR-049】洛谷7月月赛
    浅谈可持久化数据结构
    CF 888E Maximum Subsequence
    在平衡树的海洋中畅游(三)——Splay
    浅谈单调栈/队列
    CF 859E Desk Disorder
  • 原文地址:https://www.cnblogs.com/cjyyb/p/9795214.html
Copyright © 2020-2023  润新知