zoukankan      html  css  js  c++  java
  • HDU 4779:Tower Defense

    Tower Defense

    Time Limit: 4000/2000 MS (Java/Others)    Memory Limit: 132768/132768 K (Java/Others)
    Total Submission(s): 1025    Accepted Submission(s): 297


    Problem Description
      DRD loves playing computer games, especially Tower Defense games. Tower Defense is a famous computer game with a number of variations. In general, you are to build some defense towers to guard your territory in this game. 
      However, in most Tower Defense games, your defending towers will not attack each other. You will see the shells flying through your towers and finally hit the target on your screen. DRD thinks it to be absurd, and he designed a new tower defense game.
      In DRD’s game, you have two kinds of defending tower, heavy tower and light tower. You can put the tower on a grid with N rows and M columns and each cell in the grid can hold one tower at most. Both two kinds of towers can attack the cells in the same column or the same row as it is located in, and your towers may attack each other. Moreover, light towers should not be attacked by other towers while heavy towers can be attacked by at most one other tower.
      You can put some of your towers (at least one tower) in the grid to build a tower formation satisfying the restriction above. And now, DRD wants you to calculate that how many different tower formations could be designed. Note that all the towers of the same type are considered to be identical. While the answer could be quite large, you should output the number mod (109 + 7).
     
    Input
      There are multiple test cases in the input. The first line of the input file is an integer T demonstrating the number of test cases. (0< T<= 200).
      For each test case, there is only one line containing 4 integers, N, M, P and Q ,meaning that the grid has N rows and M columns, and you have P heavy towers and Q light towers. You do not have to put all the towers in the grid. (1 <= N, M <= 200, 0 <= P, Q <= 200)
     
    Output
      For each test case, output the number of different formations mod (109 + 7) in a single line.
     
    Sample Input
    3 2 2 0 1 2 2 2 0 3 3 2 1
     
    Sample Output
    4 10 144
     
    Source
     
    Recommend
    We have carefully selected several similar problems for you:  6010 6009 6008 6007 6006 

    分析:

    因为重塔有两种放法...其中一种是和轻塔一样的,所以可以视为轻塔...

    我们枚举有i行被两个棋子所占,j列被两个棋子所占...那么总占用行数为i+2*j,列数为j+2*i,使用重塔数为(i+j)*2,这个的方案数可以用组合数学搞定:c[n][i]*c[m][i<<1]*(i<<1)!/(2^i)...这是行的算法...列的算法是一样的...c[n][i]*c[m][i<<1]就不用说了...后面的就是我们已经从m列中选出了i*2列,现在我们把这些列分配给i行,第一行选择的方案数是c[i<<1][2],第二行的方案数是c[(i<<1)-2][2],第三行的方案数是c[(i<<1)-4][2]...最后一行的方案数是c[2][2]...化简一下就是(i<<1)!/(2^i)...

    然后剩下的n-(i+2*j)行和m-(j+2*i)列中选出k行k列方轻塔和重塔,应该是c[n-(i+2*j)][k]*[m-(j+2*i)][k]*(重塔方案数)...

    我们求出重塔的数量范围:Min=max(0,k-q),Max=min(k,p-2*(i+j))...所以重塔的方案数应该是c[k][Max]-c[k][Min-1]...

    然后乘起来加一加就好了...

    代码:

    WA了好久...都是细节...

    首先是2^i不能直接1LL<<i,而要预处理...因为i可能等于200...

    然后阶乘要预处理到400...

    #include<algorithm>
    #include<iostream>
    #include<cstring>
    #include<cstdio>
    //by NeighThorn
    #define int long long
    using namespace std;
    //眉眼如初,岁月如故 
    
    const int maxn=400+5,Mod=1e9+7;
    
    int n,m,p,q,cas;
    long long ans,c[maxn][maxn],po[maxn],fac[maxn],sum[maxn][maxn];
    
    inline long long power(long long x,int y){
        long long res=1;
        while(y){
            if(y&1)
                (res*=x)%=Mod;
            (x*=x)%=Mod,y>>=1;
        }   
        return res;
    }
    
    signed main(void){
    //    freopen("in.txt","r",stdin);
    //    freopen("out.txt","w",stdout);
        scanf("%lld",&cas);c[0][0]=sum[0][0]=1;
        for(int i=1;i<=400;i++)
            c[i][0]=1,c[i][i]=1,sum[i][0]=1;
        for(int i=1;i<=400;i++)
            for(int j=1;j<i;j++)
                c[i][j]=(c[i-1][j]+c[i-1][j-1])%Mod;
        for(int i=1;i<=400;i++)
            for(int j=1;j<=i;j++)
                sum[i][j]=(sum[i][j-1]+c[i][j])%Mod;
        fac[0]=1,po[0]=1;
        for(int i=1;i<=400;i++)
            fac[i]=fac[i-1]*i%Mod,po[i]=po[i-1]*2%Mod;
        while(cas--){
            scanf("%lld%lld%lld%lld",&n,&m,&p,&q);ans=0;
            for(int i=0;i<=n;i++)
                for(int j=0;j<=m;j++)
                    if(i+2*j<=n&&j+2*i<=m&&2*(i+j)<=p){
                        long long tmp=c[n][i]*c[m][2*i]%Mod*fac[i<<1]%Mod*power(po[i],Mod-2)%Mod;  
                        (tmp*=c[m-i*2][j]*c[n-i][2*j]%Mod*fac[j<<1]%Mod*power(po[j],Mod-2)%Mod)%=Mod;
                        long long lala=0LL;
                        for(int k=0;k<=p-2*(i+j)+q;k++)
                            if(k<=n-(i+2*j)&&k<=m-(j+2*i)){
                                int Max=min(k,p-2*(i+j)),Min=max(0LL,k-q);
                                long long s;
                                if(Min==0LL)
                                    s=0LL;
                                else
                                    s=sum[k][Min-1];
                                (lala+=c[n-(i+2*j)][k]*c[m-(j+2*i)][k]%Mod*fac[k]%Mod*((sum[k][Max]-s+Mod)%Mod)%Mod)%=Mod;
                            }
                        (ans+=tmp*lala%Mod)%=Mod;
                    }
            printf("%lld
    ",(ans-1+Mod)%Mod);
        }
        return 0;  
    }//Cap ou pas cap. Pas cap.
    

      


    By NeighThorn

  • 相关阅读:
    个人阅读笔记05—数据流图
    JVM(三)程序计数器【PC寄存器】
    JVM(三)运行时数据区的概述,线程概述
    JVM(二)表示两个Class对象是否为同一个类;Java程序对类的使用
    我的面试经之JVM(二)双亲委派机制
    我的面试经之JVM(二) ClassLoader补充【获取类的加载器的方式】
    我的面试经之JVM(二)类加载器的分类
    我的面试经之JVM(二)类加载器子系统ClassLoader类的加载过程
    Python小白要了解的模块大概用途(随学习进度更新),import xxxx
    Python常见的模块(知乎转载)
  • 原文地址:https://www.cnblogs.com/neighthorn/p/6284392.html
Copyright © 2011-2022 走看看