2018年全國多校算法寒假訓練營練習比賽(第二場)F - 德瑪西亞萬歲
阿新 • • 發佈:2018-01-28
code 訓練營 比賽 最優 weight -o com 英雄 tin
鏈接:https://www.nowcoder.com/acm/contest/74/F
來源:牛客網
題目描述
德瑪西亞是一個實力雄厚、奉公守法的國家,有著功勛卓著的光榮軍史。 這裏非常重視正義、榮耀、職責的意識形態,這裏的人民為此感到強烈自豪。 有一天他們想去制裁邪惡的比爾吉沃特,於是派遣了自己最優秀的戰士。 結果比爾吉沃特領土太小,只有長為n寬為m共計n*m塊土地,其中有些土 地標記為0表示為高山峻嶺或者深海湖泊,英雄們無法在其中站立,只有標 記為1的土地才能容納一個英雄。德瑪西亞的英雄們戰鬥時有一個特點,他 們不希望隊友站在自己旁邊顯得很曖昧。請問最多能有多少種安排德瑪西 亞英雄的方法?輸入描述:
輸入包含多組測試數據;
每組數據的第一行包含2個整數n和m (n <= 12, m <= 12 ),之間用空格隔開;
接下來的n行,每行m個數,表示n*m的比爾吉沃特領土。
輸出描述:
輸出一個整數n代表安排應用的方法。示例1
(答案取膜100000000)
輸入
3 3 1 1 1 0 1 1 1 0 0
輸出
24
題解
狀壓$dp$。
$dp[i][j][k]$表示到第$i$層,放置了$j$個人,且第$i$層的放置狀態為$k$的方案數。
有很多優化可以做,沒做優化也可以過。
#include <bits/stdc++.h> using namespace std; int n, m; int a[20][20]; int h[20]; long long dp[15][80][4100]; long long mod = 100000000LL; int cnt[4100], error[4100]; int limit = 75; int lowbit(int x) { return x & (-x); } void init() { for(int i = 1; i < (1 << 12); i ++) { cnt[i] = cnt[i - lowbit(i)] + 1; } for(int i = 0; i < (1 << 12); i ++) { for(int j = 0; j < 12; j ++) { int A = i & (1 << j); int B = i & (1 << (j + 1)); if(A && B) error[i] = 1; } } } int main() { init(); while(~scanf("%d%d", &n, &m)) { for(int i = 1; i <= n; i ++) { h[i] = 0; for(int j = 0; j < m; j ++) { scanf("%d", &a[i][j]); h[i] = h[i] * 2 + a[i][j]; } } dp[0][0][0] = 1; for(int i = 1; i <= n; i ++) { for(int num = 0; num <= limit; num ++) { for(int now = 0; now < (1 << m); now ++) { dp[i][num][now] = 0; if(error[now]) continue; if((now | h[i]) != h[i]) continue; if(num - cnt[now] < 0) continue; for(int pre = 0; pre < (1 << m); pre ++) { if(error[now]) continue; if(pre & now) continue; dp[i][num][now] = (dp[i][num][now] + dp[i - 1][num - cnt[now]][pre]) % mod; } } } } long long ans = 0; for(int num = 0; num <= limit; num ++) { for(int now = 0; now < (1 << m); now ++) { ans = (ans + dp[n][num][now]) % mod; } } printf("%lld\n", ans); } return 0; }
2018年全國多校算法寒假訓練營練習比賽(第二場)F - 德瑪西亞萬歲