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\n",(ans-1+Mod)%Mod);
}
return 0;
}//Cap ou pas cap. Pas cap.

  


By NeighThorn

HDU 4779:Tower Defense的更多相关文章

  1. dp --- hdu 4939 : Stupid Tower Defense

    Stupid Tower Defense Time Limit: 12000/6000 MS (Java/Others)    Memory Limit: 131072/131072 K (Java/ ...

  2. HDU 4939 Stupid Tower Defense(dp)

    题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=4939 解题报告:一条长度为n的线路,路上的每个单元格可以部署三种塔来给走在这条路上的敌人造成伤害,第一 ...

  3. HDU 4939 Stupid Tower Defense (2014 Multi-University Training Contest 7)

    思路:首先红色肯定要放在最后面.前面蓝色和绿色dp求解. dp[i][j]  表示前面(i+j) 个 有 i 个蓝色塔  j个绿色塔 能造成最大伤害. //====================== ...

  4. 2014多校第七场1005 || HDU 4939 Stupid Tower Defense (DP)

    题目链接 题意 :长度n单位,从头走到尾,经过每个单位长度需要花费t秒,有三种塔: 红塔 :经过该塔所在单位时,每秒会受到x点伤害. 绿塔 : 经过该塔所在单位之后的每个单位长度时每秒都会经受y点伤害 ...

  5. hdu 4939 Stupid Tower Defense ( dp )

    题目链接 题意:给出一条长为n个单位长度的直线,每通过一个单位长度需要t秒. 有3种塔,红塔可以在当前格子每秒造成x点伤害,绿塔可以在之后的格子每秒造成y点伤害, 蓝塔可以使通过单位长度的时间增加z秒 ...

  6. HDU 4939 Stupid Tower Defense

    dp:枚举red,dp前i 个塔中有j 个蓝塔的最大伤害. 机智的地方:dp前i 个塔的时候可以同时处理n-i 个红塔,这样就少了个循环...(枚举红塔的循环) #include <iostre ...

  7. HDU 4939 Stupid Tower Defense 简单DP

    题意: 地图为长为n个单位长度的直线,每通过一个单位长度需要t秒. 有3种塔,红塔可以在当前格子每秒造成x点伤害,绿塔可以在之后格子造成y点伤害,蓝塔可以使通过单位长度的时间增加z秒. 让你安排塔的排 ...

  8. hdu 4779 Tower Defense (思维+组合数学)

    Tower Defense Time Limit: 4000/2000 MS (Java/Others)    Memory Limit: 132768/132768 K (Java/Others) ...

  9. hdu4939 Stupid Tower Defense (DP)

    2014多校7 第二水的题 4939 Stupid Tower Defense Time Limit: 12000/6000 MS (Java/Others)    Memory Limit: 131 ...

随机推荐

  1. 第26题:LeetCode572:Subtree of Another Tree另一个树的子树

    题目描述 给定两个非空二叉树 s 和 t,检验 s 中是否包含和 t 具有相同结构和节点值的子树.s 的一个子树包括 s 的一个节点和这个节点的所有子孙.s 也可以看做它自身的一棵子树. 示例 1: ...

  2. tab菜单的点击的动态效果和内容页面的关联显示jQuery

    <!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8&quo ...

  3. python实现导出excel表(前端+后端)

    之前在做项目管理系统的时候需要实现将数据导出到excel表的功能,搜索之后发现了python的xlwt模块可以很好的实现这项功能. 首先是导入xlwt模块: import xlwtfrom io im ...

  4. Union found

    Use array. class UnionFound { public: vector<int> v; int cnt; UnionFound(int n) { v = vector&l ...

  5. ubuntu怎样打开终端

    1.首先在桌面任意空白处,按CTRL+ALT+T 2.方法二

  6. Air Pollution【空气污染】

    Air Pollution Since the 1940s, southern California has had a reputation for smog. 自20世纪40年代以来,南加利福尼亚 ...

  7. 排列算法汇总(下一个排列,全排列,第K个排列)

    一.下一个排列 首先,STL提供了两个用来计算排列组合关系的算法,分别是next_permutation和prev_permutation. next_permutation(nums.begin() ...

  8. 洛谷 P2205 [USACO13JAN]画栅栏

    这题其实没什么,但用到的算法都十分有用.做一个不恰当的比喻,这是一只必须用牛刀杀的鸡,但因为我这个蒟蒻杀不死牛,所以只能找只鸡来练练手. 题目描述 Farmer John 想出了一个给牛棚旁的长围墙涂 ...

  9. 按位与&、或|、异或^等运算方法

    (转载) 按位与运算符(&) 参加运算的两个数据,按二进制位进行“与”运算. 运算规则:0&0=0;   0&1=0;    1&0=0;     1&1=1; ...

  10. D3DXCreateTextureFromFile

    HRESULT D3DXCreateTextureFromFile( __in LPDIRECT3DDEVICE9 pDevice, __in LPCTSTR pSrcFile, __out LPDI ...