初始化:
状态表示:
状态计算:
结果:求最多交易\(k\)次,所获得的最大利益
状态表示:
状态计算:
\(dp[i][1]\)
\(dp[i - 1][0] + w[i]\):前一天手中有存货,卖掉了
\(dp[i][2]\)
如果横放的长方形摆放好了,那么竖放的长方形的摆放的方案数就确定了,因此只需考虑横放的数量即可
\(dp[i][j]\)表示第\(i\)列,上一列中那些行伸出来的小方格状态数,伸出来记为1,否则值为零,由此产生的二进制数的十进制表示
两个转移条件:
#include <iostream>
#include <cstring>
#include <vector>
using namespace std;
const int N = 12, M = 1 << N;
int n, m;
long long dp[N][M];
bool st[M];
vector<int> states[M];
int main() {
while(cin >> n >> m , n || m) {
for(int i = 0; i < 1 << n; i++) {
st[i] = true;
int cnt = 0;
for(int j = 0; j < n; j++) {
if(i >> j & 1) {
if(cnt & 1) {
st[i] = false;
break;
}
}
else cnt++;
}
if(cnt & 1) st[i] = false;
}
// cout << endl;
for(int i = 0; i < 1 << n; i++) {
states[i].clear();
for(int j = 0; j < 1 << n; j++) {
if((i & j) == 0 && st[i | j])
states[i].push_back(j);
}
}
memset(dp, 0, sizeof dp);
dp[0][0] = 1;
for(int i = 1; i <= m; i++) {
for(int j = 0; j < 1 << n; j++) {
for(auto k : states[j]) {
dp[i][j] += dp[i - 1][k];
}
}
}
cout << dp[m][0] << endl;
}
return 0;
}
#include <iostream>
#include <cstring>
#include <vector>
using namespace std;
typedef long long LL;
const int N = 12, M = 1 << 10, K = 110;
LL dp[N][K][M];
int cnt[M], n, m;
vector<int> h[M];
vector<int> states;
// 判断每行中是否中所有合法的状态:不含有相邻的不为1的数
bool check(int state) {
for(int i = 0; i < n; i++)
if((state >> i & 1) && (state >> i + 1 & 1))
return false;
return true;
}
// 计算该状态在一行中放置的棋子数量
int count(int state) {
int res = 0;
for(int i = 0; i < n; i++) res += (state >> i & 1);
return res;
}
int main() {
cin >> n >> m;
// 预处理各种可行的状态,存入states数组
for(int i = 0; i < 1 << n; i++) {
if(check(i)) {
states.push_back(i);
cnt[i] = count(i);
}
}
// 枚举可行的状态,将两者可以作为上下行的存入h数组
for(int i = 0; i < states.size(); i++) {
for(int j = 0; j < states.size(); j++) {
int a = states[i], b = states[j];
if((a & b) == 0 && check(a | b))
h[i].push_back(j);
}
}
// 什么都没放的方案数为1
dp[0][0][0] = 1;
// 枚举每行
for(int i = 1; i <= n + 1; i ++) {
// 枚举所有的棋子
for(int j = 0; j <= m; j++) {
// 遍历所有的可行的状态
for(int a = 0; a < states.size(); a++) {
for(auto b : h[a]) {
int c = cnt[states[a]];
if(j >= c)
dp[i][j][a] += dp[i - 1][j - c][b];
}
}
}
}
cout << dp[n + 1][m][0];
return 0;
}
#include <iostream>
#include <vector>
using namespace std;
const int N = 110, M = 12;
int g[N], cnt[1 << M];
int n, m;
int dp[N][1 << M][1 << M];
vector<int> states;
vector<int> h[1 << M];
// 行与行之间不能有交集
bool check(int state) {
for(int i = 0; i < m; i++)
if((state >> i & 1) && ((state >> i + 1 & 1) || (state >> i + 2 & 1)))
return false;
return true;
}
int count(int state) {
int res = 0;
for(int i = 0; i < m; i++) res += (state >> i & 1);
return res;
}
int main() {
cin >> n >> m;
for(int i = 1; i <= n; i++) {
for(int j = 0; j < m; j++) {
char c; cin >> c;
// 此处为山地,不能摆放炮团,标记为1
g[i] += (c == ‘H‘) << j;
}
}
for(int i = 0; i < 1 << m; i++)
if(check(i)) {
states.push_back(i);
cnt[i] = count(i);
}
for(int i = 1; i <= n + 2; i++)
// 枚举i行状态
for(int j = 0; j < states.size(); j++)
// i - 1状态
for(int k = 0; k < states.size(); k++)
// i - 2状态
for(int l = 0; l < states.size(); l++) {
int curr = states[j], r1 = states[k], r2 = states[l];
if((r1 & r2) | (r1 & curr) | (curr & r2)) continue;
if((g[i] & curr) | (g[i - 1] & r1)) continue;
dp[i & 1][j][k] = max(dp[i & 1][j][k], dp[i - 1 & 1][k][l] + cnt[curr]);
}
cout << dp[n + 2 & 1][0][0];
return 0;
}
// 初始化
memset(dp, 0x3f, sizeof dp);
// 开始,途径第零个点
dp[1][0] = 0;
for(int i = 0; i < 1 << n; i++)
for(int j = 0; j < n; j++)
// 如果经过这个点的话
if(i >> j & 1) {
for(int k = 0; k < n; k++) {
if(((i - (1 << j)) >> k) & 1)
dp[i][j] = min(dp[i][j], dp[i - (1 << j)][k] + a[k][j]);
}
}
cout << dp[(1 << n) - 1][n - 1];
原文:https://www.cnblogs.com/Hot-machine/p/13335575.html