• 【BZOJ3193】[JLOI2013]地形生成 DP


    【BZOJ3193】[JLOI2013]地形生成

    Description

    最近IK正在做关于地形建模的工作。其中一个工作阶段就是把一些山排列成一行。每座山都有各不相同的标号和高度。为了遵从一些设计上的要求,每座山都设置了一个关键数字,要求对于每座山,比它高且排列在它前面的其它山的数目必须少于它的关键数字。
     显然满足要求的排列会有很多个。对于每一个可能的排列,IK生成一个对应的标号序列和等高线序列。标号序列就是按顺序写下每座山的标号。等高线序列就是按顺序写下它们的高度。例如有两座山,这两座山的一个合法排列的第一座山的标号和高度为1和3,而第二座山的标号和高度分别为2和4,那么这个排列的标号序列就是1 2,而等高线序列就是3 4.
     现在问题就是,给出所有山的信息,IK希望知道一共有多少种不同的符合条件的标号序列和等高线序列。

    Input

    输入第一行给出山的个数N。接下来N行每行有两个整数,按照标号从1到N的顺序分别给出一座山的高度和关键数。

    Output

    输出两个用空格分隔开的数,第一个数是不同的标号序列的个数,第二个数是不同的等高线序列的个数。这两个答案都应该对2011取模,即输出两个答案除以2011取余数的结果

    Sample Input

    2
    1 2
    2 2

    Sample Output

    2 2

    HINT

    对于所有的数据,有1<=N<=1000,所有的数字都是不大于109的正整数。

    题解:显然,我们的思路是将所有山按高度排序,然后从大到小扔到序列中去。那么第一问就做完了,考虑第二问。

    因为山的高度相同但是关键值不同,那么我们可以认为规定:对于相同高度的山,关键值大的排在关键值小的后面,这样很巧妙的避免了重复。那么直接DP,用f[i]表示在相同高度的山中,最后一个的位置是i的方案数,O(n^2)转移即可。

    #include <cstdio>
    #include <cstring>
    #include <iostream>
    #include <algorithm>
    using namespace std;
    const int maxn=1010;
    const int mod=2011;
    int n,ans,sum,last;
    struct node
    {
    	int h,k;
    }p[maxn];
    int f[maxn];
    inline int rd()
    {
    	int ret=0,f=1;	char gc=getchar();
    	while(gc<'0'||gc>'9')	{if(gc=='-')f=-f;	gc=getchar();}
    	while(gc>='0'&&gc<='9')	ret=ret*10+gc-'0',gc=getchar();
    	return ret*f;
    }
    bool cmp2(node a,node b)
    {
    	return (a.h==b.h)?(a.k<b.k):(a.h>b.h);
    }
    int main()
    {
    	n=rd();
    	int i,j;
    	for(i=1;i<=n;i++)	p[i].h=rd(),p[i].k=rd();
    	sort(p+1,p+n+1,cmp2),p[0].h=1<<30;
    	for(ans=i=1;i<=n;i++)
    	{
    		if(p[i].h<p[i-1].h)	j=0;
    		ans=ans*min(i,p[i].k+j)%mod,j++;
    	}
    	printf("%d ",ans);
    	f[0]=1;
    	for(ans=i=1;i<=n;i++)
    	{
    		if(p[i].h<p[i-1].h)
    		{
    			last=i-1;
    			for(sum=0,j=0;j<=last;j++)	sum=(sum+f[j])%mod;
    			memset(f,0,sizeof(f));
    			for(j=0;j<p[i].k&&j<=last;j++)	f[j]=sum;
    		}
    		else
    		{
    			for(sum=0,j=0;j<p[i].k&&j<=last;j++)	sum=(sum+f[j])%mod,f[j]=sum;
    		}
    	}
    	for(sum=0,i=0;i<=n;i++)	sum=(sum+f[i])%mod;
    	printf("%d",sum);
    	return 0;
    }
  • 相关阅读:
    深度排序与alpha混合 【转】
    SVN服务器配置说明 【转】
    3D空间中射线与轴向包围盒AABB的交叉检测算法 【转】
    Linux系统管理员不可不知的命令:sudo
    Linux 系统实时监控的瑞士军刀 —— Glances
    shell定期转移日志文件到云盘并定期删除云盘文件
    zabbix监控第二块网卡是否连通
    Gitlab自动触发Jenkins构建打包
    shell脚本检测网络是否畅通
    Prometheus入门
  • 原文地址:https://www.cnblogs.com/CQzhangyu/p/7367526.html
Copyright © 2020-2023  润新知