1. 程式人生 > >洛谷 模擬城市2.0

洛谷 模擬城市2.0

std thml badge bit spa 遮擋 mil oid under

一次洛谷月賽的T1,當時因為是信心賽,認為第一題應該不會太難,結果想了很久,直接額放棄正解選擇暴力。。。簡直就是巨坑的五維DP。。。mmd

題目背景

博弈正在機房頹一個叫做《模擬城市2.0》的遊戲。

2048年,經過不懈努力,博弈終於被組織委以重任,成為D市市委書記!

他勤學好問,勵精圖治,很快把D市建設成富強民主文明和諧的美好城市。為了進一步深化發展,他決定在海邊建立一個經濟開發區。

題目描述

已知開發區的建築地塊是一個n×n的矩形,而開發區可以建造三種建築: 商業樓,住宅樓,教學樓。這任何兩座建築可以堆疊,可以緊密相鄰。他需要建造正好a座商業樓,b座住宅樓,c座教學樓。但是,城市建成後要應付檢查,如果安排的太混亂會被批評。不過幸運的是,只有一條公路經過了該開發區的一側,就是說,檢察人員全程只能看到開發區的一面。

因此,他需要使得開發區建成後,從正面看去,只有一種類型的建築。

一共有多少種滿足條件的方案呢? 請輸出方案數,並對10^9+7取模。

註意,對於同一個n,會有多組數據。

輸入輸出格式

輸入格式:

第一行兩個整數n,T

接下來T行,每行三個整數,表示該組數據的a,b,c

輸出格式:

輸出共T行,每行一個整數:表示各數據答案取模10^9+7的結果。

輸入輸出樣例

輸入樣例#1:
2 1
1 1 0
輸出樣例#1:
4
輸入樣例#2:
2 1
2 1 0
輸出樣例#2:
8

說明

對於20%的數據,n2 a,b,c3 T5

對於另外10%的數據,n3 a,b,c4 T5

對於另外20%的數據,b=0

對於另外10%的數據,T10

對於全部100%的數據,a,b,c,n25 T5×105

樣例1

技術分享圖片

技術分享圖片

樣例2

技術分享圖片

Solution:

正解DP+組合數。(可能有多種方法,這裏說其中的一種)我們發現,從正面看,橫排放置的方塊會互相影響(因為後面的可能比前面高,狀態太復雜且不好轉移),我們可以考慮縱向放置的方案數。縱列和縱列之間不會相互遮擋,因此方案數很好統計。

所以我們需要處理出縱列合法的方案數。雖然有三種方塊,但我們只是需要一種漏在外面,所以可以把另外兩種先不考慮,把它們合成一個狀態。


處理任意一列合法方案數,可以dfs處理,也可以dpf[i][j][k][x][y]表示放置到第 i個格子,高度為 j,已經放置的最高高度為 k,已經用了 x個能看見的方塊,y 個不能看見的方塊的方案數邊界條件:最高可以放到max(a,b,c),我們發現如果高度超過了所有種類顏色的數量,那麽我們不可能使得這種情況合法。需要註意的是, y的最大值應當是2*max(a,b,c),因為我們把另外兩種方塊整合在一起了。那麽就可以按順序暴力的放置了。每個格子可能有兩種操作,在它上面放一個新的格子,或者把下一個格子放到下一行去。如果下個位置的高度超過了枚舉的最高高度,那麽前面就沒有格子可以遮擋它,它必須放能看見的種類,並更新最高高度。否則說明下個位置的高度不夠高,會被前面已經放置的格子遮擋,那麽放什麽種類就都可以啦。

狀態轉移方程:

放到下一行:
f[i+1][0][k][x][y]+=f[i][k][k][x][y];
放到上面:
if (j==k)
f[i][j+1][k+1][x+1][y]+=f[i][j][k][x][y];
else
f[i][j+1][k][x+1][y]+=f[i][j][k][x][y],
f[i][j+1][k][x][y+1]+=f[i][j][k][x][y];
復雜度O(n5)

為了方便統計,標程的 i計算到了n+1這樣我們就可以處理出,因為i=n的所有情況都統計在了f[n+1][0]中。

這樣我們就可以處理出g[i][j]表示在某一列上,用了i 種能看見的方塊,j 種遮擋住的方塊的方案數。每一行的方案數處理出來了,我們就可以開始真正的dp了。

dp[i][j][k]表示從左往右(正面)放到第i 列,用了j 種能看見的方塊, k種遮擋的方塊的方案數。dp[i+1][j+x][y+k]+=dp[i][j][k]*g[x][y];

復雜度O(n5)

處理出dp數組之後,實際上我們就得到了答案的一部分。如果只有兩種方塊可供放置,那麽dp數組就是答案了就是我先前說的b=0的部分。

但是我們有三種方塊。考慮讓一種方塊漏出來,那麽另外兩種方塊的位置是可以隨意組合的(因為並不會漏在外面)。所以還需要處理一下組合數。數據範圍很小,可以直接預處理。如果只讓一種(如住宅樓)能看見,那麽方案數已經顯而易見了。

dp[n][a][b+c]*C[c+b][b];

dp表示使得a 漏在外面,b,c遮住的方案數。C 數組是組合數,表示一共有b+c個位置,b、c隨意組合的方案數。

那麽最終答案就呼之欲出了。

代碼:

 1 #include<bits/stdc++.h>
 2 #define mod 1000000007
 3 #define N 27
 4 using namespace std;
 5 inline int read()
 6 {
 7     int x=0,f=1;char ch=getchar();
 8     while(ch<0||ch>9){if(ch==-)f=-1;ch=getchar();}
 9     while(ch>=0&&ch<=9){x=x*10+ch-0;ch=getchar();}
10     return x*f;
11 }
12 int f[N][N][N][N][N<<1],g[N][N<<1],C[N<<1][N<<1],dp[N][N][N<<1];
13 int ans,a,b,c,n,m,T;
14 inline void add(int &x,int y){x+=y;if (x>=mod) x-=mod;}
15 main()
16 {
17     n=read(),T=read();
18     m=25;
19     f[0][0][0][0][0]=1;
20     for (int i=0;i<n;i++)
21         for (int j=0;j<=m;j++)
22             for (int k=j;k<=m;k++)
23                 for (int x=k;x<=m;x++)
24                     for (int y=0;y<=(m<<1);y++)
25                         if (f[i][j][k][x][y])
26                         {
27                             add(f[i+1][0][k][x][y],f[i][j][k][x][y]);
28                             if (j==k)
29                                 add(f[i][j+1][k+1][x+1][y],f[i][j][k][x][y]);
30                             else
31                                 add(f[i][j+1][k][x+1][y],f[i][j][k][x][y]),
32                                 add(f[i][j+1][k][x][y+1],f[i][j][k][x][y]);
33                         }
34     for (int k=0;k<=m;k++)
35         for (int x=k;x<=m;x++)
36             for (int y=0;y<=(m<<1);y++)
37                 add(g[x][y],f[n][0][k][x][y]);
38     C[0][0]=1;
39     for(int i=1;i<=(m<<1);i++)
40     {
41         C[i][0]=1;
42         for(int j=1;j<=i;j++)
43         {
44             C[i][j]=C[i-1][j-1]+C[i-1][j];
45             if (C[i][j]>=mod) C[i][j]-=mod;
46         }
47     }
48     dp[0][0][0]=1;
49     for (int i=0;i<n;i++)
50         for (int j=0;j<=m;j++)
51             for (int k=0;k<=(m<<1);k++)
52                 if (dp[i][j][k])
53                     for(int x=0;j+x<=m;x++)
54                         for(int y=0;y+k<=(m<<1);y++)
55                             add(dp[i+1][j+x][y+k],(1ll*dp[i][j][k]*g[x][y])%mod);
56     while(T--)
57     {
58         a=read(),b=read(),c=read();
59         ans=0;
60         add(ans,(1ll*dp[n][a][b+c]*C[b+c][b])%mod);
61         add(ans,(1ll*dp[n][b][c+a]*C[c+a][c])%mod);
62         add(ans,(1ll*dp[n][c][a+b]*C[a+b][a])%mod);
63         printf("%d\n",ans);    
64     }
65 }

技術分享圖片

洛谷 模擬城市2.0