• 【洛谷8100】[USACO22JAN] Counting Haybales P(DP)


    题目链接

    • 给定一个长度为 \(n\) 的序列,可以无限交换相邻两个值恰好相差 \(1\) 的数。
    • 求可能得到多少种序列。
    • \(1\le n\le5\times10^3\)

    可以交换的条件

    发现两个数的顺序能改变,充要条件是 它们恰好相差 \(1\)它们之间所有数都与它们中的某一个恰好相差 \(1\) ,因为只有才能让它们两个相邻然后发生交换。这可以预处理出来。

    仅从这个条件出发并不好做,因为状态什么的都很难表示。

    考虑到既然要恰好相差 \(1\),那么一个必要条件就是奇偶性相同的数的相对顺序不能变。

    所以先把所有数按奇偶性分成两部分,同一部分中的数相对顺序是确定的,只能一个一个按序加入最终序列。

    即,设 \(f_{i,j}\) 表示已经填了 \(i\) 个奇数、\(j\) 个偶数的方案数。

    每次转移时,只要保证这次填入的数能在上次填入的与它奇偶性不同的那个数后面即可。

    代码:\(O(n^2)\)

    #include<bits/stdc++.h>
    #define Tp template<typename Ty>
    #define Ts template<typename Ty,typename... Ar>
    #define Rg register
    #define RI Rg int
    #define Cn const
    #define CI Cn int&
    #define I inline
    #define W while
    #define N 5000
    #define X 1000000007
    using namespace std;
    int n,a[N+5],c[2],q[2][N+5],f[N+5][N+5],p[N+5][N+5];
    int main()
    {
    	RI Tt,i,j,mn,mx;scanf("%d",&Tt);W(Tt--)
    	{
    		for(scanf("%d",&n),c[0]=c[1]=0,i=1;i<=n;++i) scanf("%d",a+i),q[a[i]&1][++c[a[i]&1]]=i;//按奇偶性分成两部分
    		for(i=1;i<=n;++i) for(mn=mx=a[i],j=i;j<=n;++j)//预处理两个数顺序能否改变
    			mn=min(mn,a[j]),mx=max(mx,a[j]),p[i][j]=abs(a[i]-a[j])<=1&&min(a[i],a[j])-mn<=1&&mx-max(a[i],a[j])<=1;//它们相差1;中间都与某个相差1
    		for(i=0;i<=c[0];++i) for(j=0;j<=c[1];++j) f[i][j]=0;//清空
    		#define OK(x,y) (x<y||p[y][x])//判断y能否在x后面
    		for(f[0][0]=1,i=0;i<=c[0];++i) for(j=0;j<=c[1];++j)
    			i^c[0]&&(!j||OK(q[1][j],q[0][i+1]))&&(f[i+1][j]=(f[i+1][j]+f[i][j])%X),//尝试填偶数
    			j^c[1]&&(!i||OK(q[0][i],q[1][j+1]))&&(f[i][j+1]=(f[i][j+1]+f[i][j])%X);//尝试填奇数
    		printf("%d\n",f[c[0]][c[1]]);
    	}return 0;
    }
    
  • 相关阅读:
    JavaScript数组API
    爱上经典之王梦麟《阿美阿美》
    爱上经典之《蜗牛与黄鹂鸟》
    爱上经典之《兰花草》
    爱上经典之《让我们看云去》
    爱上经典之卓依婷《三月里的小雨》
    爱上经典之孟庭苇《冬季到台北来看雨》
    有故事看SQA作用
    转自scmlife趣谈质量管理与工程改进面试
    Mysql之批处理
  • 原文地址:https://www.cnblogs.com/chenxiaoran666/p/Luogu8100.html
Copyright © 2020-2023  润新知