zoukankan      html  css  js  c++  java
  • HDU 4783 Clumsy Algorithm

    题意不提。

      我们可以发现,可以将最终序列分为对于第i个位置i-pi>=0与i-pi<0种两个子序列。且如果f[n]==g[n],则有两个子序列都递增。

      原因是f[n]表示1-n这个排列的逆序对个数,即冒泡排序的交换次数,而每个g[i]表示将p[i]从i位置移到它应当在的p[i]位置的交换次数。

      考虑将每个满足i-p[i]>0的p[i]从i位置移到p[i]位置是正确的条件,显然对于i-p[i]>0的每个p[i]必须递增,否则,会产生p[i]与p[j]交换时的交叉,使冒泡的代价增大。

      若 i-p[i]<0 的p[i]不递增,它们之间会产生新的冒泡,使冒泡的代价增加。

      所以就是DP了,设f[i][j]表示已放了j个数,其中最大数为i的且满足限制的方案数,显然如果j+1的位置放i-p[i]<0的,直接枚举i+1-n的数字即可。

      若j+1的位置放i-p[i]>=0的数字,由于i-p[i]>=0的数字必须递增,且i递增,因此有一个必选的数字直接填入即可。

      直接转移即可。

      

    #include<bits/stdc++.h>
    #define MOD 1000000007
    using namespace std;
    #define FILE "chad"
    set<int> S;
    int n, k, f[105][105];
    
    int main()
    {
    	//freopen(FILE".in","r",stdin);
    	//freopen(FILE".out","w",stdout);
    	int T; scanf("%d",&T);
    	for(int tt = 0;T--;)
    	{
    		memset(f, 0, sizeof f);
    		S.clear();
    	
    		scanf("%d%d",&n,&k);
    		for(int i = 1; i <= n; i++) S.insert(i);
    		int mx = 0, flag = 1;
    		for(int i = 1; i <= k; i++)
    		{
    			int x; scanf("%d",&x);
    			if(x > mx)
    			{
    				mx = x;
    				
    			}
    			else if(x != *S.begin()) flag = 0;
    			S.erase(x);
    		}
    		f[mx][k] = flag;
    		for(int i = 0; i <= n; i++)
    		{
    			for(int j = 0; j < n; j++)
    			{
    				if(i-j > 0) (f[i][j+1] += f[i][j]) %= MOD;
    				for(int k = i+1; k <= n; k++)
    					(f[k][j+1] += f[i][j]) %= MOD;
    			}
    		}
    		printf("Case #%d: %d
    ",++tt,f[n][n]);
    		
    	}
    }
    
    //代码来自某AC代码,侵删。
    

      

  • 相关阅读:
    SQL Server 阻止了对组件 'Ole Automation Procedures' 的 过程'sys.sp_OACreate' 的访问
    谷歌浏览器扩展程序manifest.json参数详解
    获取天气api
    UVA 10385 Duathlon
    UVA 10668 Expanding Rods
    UVALIVE 3891 The Teacher's Side of Math
    UVA 11149 Power of Matrix
    UVA 10655 Contemplation! Algebra
    UVA 11210 Chinese Mahjong
    UVA 11384 Help is needed for Dexter
  • 原文地址:https://www.cnblogs.com/chadinblog/p/9311299.html
Copyright © 2011-2022 走看看