hdu5555(状态压缩dp)

Immortality of Frog

Time Limit: 8000/4000 MS (Java/Others)    Memory Limit: 65536/65536 K (Java/Others)
Total Submission(s): 494    Accepted Submission(s): 178


Problem Description
N frogs are attempting to prolong their life-span. They live in the bottom of a well which can be described as a two-dimensional  N×N grid.  Grid(i,j) is located in the  ith row and the  jth column. At the beginning, the  ith frog lives in the bottom of  ith column, i.e. the place below  grid(1,i).
The frogs are so devout that God decides to give them a chance. In each row  i, a horizontal membrane ranging from  (i,Li) to  (i,Ri) inclusively is created. A capsule of elixir is placed at one of the grids of the membrane with uniform probability.

Now the frogs are jumping upwards to pursue immortality. The  ith frog would be in  grid(j,i) after  j jumps. When a frog arrives at a grid that contains a capsule of elixir, it will eat the capsule and gain immortality. After that, it continues jumping upwards until it gets out of the well.

A membrane is considered “ bad” if it convers less than  N grids. The frogs are very sensitive, so they can only endure passing through 10 bad membrane. When a frog reaches the  11th bad membrane, it thinks that there is no hope to get out of the well, so it will go back to the bottom of well and live there until death, even though it has eaten a capsule of elixir already.

The frogs are friends, so they want all of them gain immortality and live a happy life out of the well. They want to know the probability  P that every frog eats exactly one capsule of elixir and gets out of the well.
 

Input
The first line of input contains a number  T indicating the number of test cases ( T100).

Each test case starts with a line containing an integer  N as described above ( 1N1000). The second line contains  N space separated integers  L1,L2,...,LN. The third line contains  N space separated integers  R1,R2,...,RN. ( 1LiRiN)
 

Output
For each test case, output a single line consisting of “ Case #X: Y”.  X is the test case number starting from 1.  Y is an integer defined as the probability  P multiplies  Ni=1(RiLi+1) . As the answer could be huge, you only need to output it module 105225319.
 

Sample Input
 
  
2 2 1 2 1 2 2 1 1 2 2
 

Sample Output
 
  
Case #1: 1 Case #2: 2

题意:给你一个NxN的网格,第N行的每一列都有个青蛙,这些青蛙只会往上走,上帝会在每个膜中放一个长生不老的药,一共有N个膜,每个膜覆盖一些区间,如果这个区间恰好为N那么就是好膜,否则是坏膜,每个青蛙最多只能穿过10个坏膜,问全部青蛙吃到药,并全部到顶层的分配方案。


思路:对于坏膜和好膜分开来算,先计算坏膜的方案数,然后剩下来好膜就是阶乘即可。对于坏膜,由于每列最多10个,我们对其进行状态压缩,dp[i][j]表示前第i列,且第i列中坏膜使用情况数为j的方案数。然后转移过程中需要注意每个都是相对位置。到达最后一列的应该是所有坏膜的使用的。而且在转移过程中到达一个坏膜的最右边了,那么dp[i][j]中这个膜一定是使用了的。


#include <iostream>
#include <stdio.h>
#include <string.h>
#include <math.h>
#include <algorithm>
#include<vector>
using namespace std;
typedef long long ll;
typedef unsigned long long ull;
const double eps = 1e-20;
const ll _INF = 1e18;
const int INF = 1e9;
const int maxn = 1010;
const int maxm = 1e6 + 10;
const ll mod = 105225319;
int T, cas = 1;
int n, tol;
int l[maxn], r[maxn], a[maxn];
ll fac[maxn];
vector<int> g[maxn];
ll dp[maxn][1<<10];
int mp[maxn][12];
void ini(){
	fac[0] = 1;
	for(int i=1;i<maxn;++i)
		fac[i] = fac[i - 1] * i % mod;
}
int main()
{
	ini();
	scanf("%d", &T);
	while(T--){
        memset(dp,0,sizeof(dp));
		memset(a, 0, sizeof(a));
        memset(mp,0,sizeof(mp));
		scanf("%d", &n);
        for(int i=0;i<=n;i++)g[i].clear();
		for(int i=1;i<=n;++i)
			scanf("%d", &l[i]);
		for(int i=1;i<=n;++i)
        {
			scanf("%d", &r[i]);
			if(l[i]>1 || r[i]<n){
				++a[l[i]];
				--a[r[i] + 1];
			}
        }
		bool isok = true;
		int sum = 0;
		for(int i=1;i<=n;++i){
			sum += a[i];
			if(sum > 10){
				isok = false;
				break;
			}
		}
		if(isok){
			ll ans;
			int cnt = 0;
            bool flag=false;
			for(int i=1;i<=n;++i)
            {
				if(l[i] == 1 && r[i] == n){
					++cnt;
				}
				else
                {
                    flag=true;
                    for(int j=l[i];j<=r[i];j++)
                    {
                        g[j].push_back(i);
                    }
                }
            }
			ans = fac[cnt];
			if(flag){
                int st;
                for(int i=1;i<n;i++)
                {
                    st=0;
                    for(int j=0;j<g[i].size();j++)
                    {
                        for(int k=st;k<g[i+1].size();k++)
                        {
                            if(g[i][j]==g[i+1][k])
                            {
                                mp[i][j+1]=k+1;
                                st=k+1;
                                break;
                            }
                        }
                    }
                }
				for(int i=0;i<g[1].size();i++)
                {
                    dp[1][1<<i]=1;
                }	
                dp[1][0]=1;   

                for(int i=1;i<n;i++)
                {
                    for(int j=0;j<(1<<g[i].size());j++)
                    {
                        if(dp[i][j])
                        {
                            int k=0;
                            bool f=true;
                            for(int pc=0;pc<g[i].size();pc++)
                            {
                                if(mp[i][pc+1])
                                {
                                    if((mp[i][pc+1]-pc-1)>=0)k|=((j&(1<<pc))<<(mp[i][pc+1]-pc-1));
                                    else k|=((j&(1<<pc))>>(-mp[i][pc+1]+pc+1));
                                }
                                else if((j&(1<<pc))==0)
                                {
                                    f=false;
                                    break;
                                }
                            }
                            if(!f)continue;
                            dp[i+1][k]=(dp[i+1][k]+dp[i][j])%mod;
                            for(int pc=0;pc<g[i+1].size();pc++)
                            {
                                if(((k>>pc)&1)==0)
                                {
                                    dp[i+1][k|(1<<pc)]=(dp[i+1][k|(1<<pc)]+dp[i][j])%mod;
                                }
                            }
                        }
                    }
                }
                ans=(ans*dp[n][(1<<g[n].size())-1])%mod;
			}
			printf("Case #%d: %lld\n", cas++, ans);			
		}
		else{
			printf("Case #%d: 0\n", cas++);
		}
	}
    return 0;
}





猜你喜欢

转载自blog.csdn.net/qq_25576697/article/details/80901215