poj 2441 狀態壓縮 滾動陣列 剪枝DP

2021-07-04 11:12:17 字數 1492 閱讀 4390

題意:

有n(20)只牛和m(20)個籃球場,每個籃球場只能乙隻牛打,然後每只牛都有自己喜好的籃球場。

現在問有多少種分配方法使得每只牛都能在自己喜歡的籃球場打球,並且這個球場只有它乙隻牛。

解析:首先是狀壓:

dp[ i ] [ state ] 表示的是第i隻牛球場狀態為state時的分配方法數。

狀態轉移方程也很好推:

dp[ i ] [ state | (1 << (v - 1)) ] = ∑ dp[ i - 1 ] [ state ]。

其中v代表的是當前牛i喜歡的球場v。

然後超記憶體。

改滾動陣列:

dp[i & 1][state | (1 << (v - 1))] += dp[1 - (i & 1)][state]。

然後超時。

加剪枝:

如果前一狀態 dp[1 - (i & 1)][state] 是0,說明這個狀態無法到達,也就不用花費乙個遍歷了。

把n只牛下的每種符合情況的狀態加起來就ok了。

加的時候可以列舉,也可以用列舉k子集的方法。

k子集的意思是狀態壓縮完了的二進位制裡面有k個1的狀態從小到大的列舉。

好像快不了多少,還re了一發。

int ans = 0;

int comb = (1 << n) - 1;

ans += dp[n & 1][comb];

while (comb < (1 << m))

**:

#include #include #include #include #include #include #include #include #include #include #include #include #define ll long long

#define lson lo, mi, rt << 1

#define rson mi + 1, hi, rt << 1 | 1

using namespace std;

const int inf = 0x3f3f3f3f;

const int maxn = (1 << 20) + 10;

int n, m;

int dp[2][maxn];

vectorcow[30];

int main()

for (int i = 1; i <= n; i++)

}memset(dp, 0, sizeof(dp));

dp[0][0] = 1;

for (int i = 1; i <= n; i++)}}

}memset(dp[1 - (i & 1)], 0, sizeof(dp[1 - (i & 1)]));

}int ans = 0;

for (int i = 0; i < (1 << m); i++)

printf("%d\n", ans);

}return 0;

}

POJ 1324(A 狀態壓縮)

真是好題啊,各種tle之後看了人家的解題報告才a的 1 一開始用deque儲存狀態資訊,用queue進行bfs,tle 2 試圖用陣列儲存狀態資訊,自己寫佇列進行bfs,還是tle 3 由於row和col都小於20,試圖用5 2個bit表示乙個位置,還是tle 終於看了discuss,找到了大牛的解...

1185 POJ 狀態壓縮

這道題寫的我直 寫了6遍,不知道 錯了,然後按照題解,一點一點寫下來,跪哭了,太渣了 ps include include include include include include include include include include include define ll int64 ...

3311 POJ 狀態壓縮

include include include include include include include include include include define ll int64 define lll unsigned long long define max 1000009 defin...