刚开始学插头dp好吃力,看了别人的代码有点看不懂,所以就参考了别人的代码,写了注释,希望有帮助
如果看不懂可以问
//下面所说的情况全在论文中的第13页
#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
#define N 13
#define S1 14000
#define S2 1600000
struct Queue{
int opt;
long long sum;
}Q[2][S1];
char g[N][N];
int pow3[N];
//cnt指的是状态有多少种
int cnt[2];
//state[][j]指的是j这种状态的序号是多少
int state[2][S2];
int n, m, final, now;
//得到第col列的状态
int get(int opt, int col) {
return opt / pow3[col] % 3;
}
//将第col列设置成value
int set(int opt, int col, int value) {
return opt + (value - get(opt, col)) * pow3[col];
}
//这是记忆化宽度优先搜索的的解法,插入队列
void enqueue(int opt, int col, long long sum) {
//如果是最后一列,且最后一列还有右插头,这就不符合了,第m个存储的是第col列的右插头
if (col == m - 1 && get(opt, m))
return ;
//找出opt这个状态的序号
int &id = state[now][opt];
//如果拓展过
if (id)
Q[now][id].sum += sum;
else {
//没拓展过
id = ++cnt[now];
Q[now][id].opt = opt;
Q[now][id].sum = sum;
}
}
//改变状态,这种情况是论文中的情况2.1
int change1(int opt, int i) {
for (int flag = 0; i < m; i++) {
int tmp = get(opt, i);
if (tmp == 1)
flag++;
else if (tmp == 2)
flag--;
if (!flag)
return set(opt, i, 1);
}
return -1;
}
//改变状态,这种情况是论文中的情况2.2
int change2(int opt, int i) {
for (int flag = 0; i >= 0; i--) {
int tmp = get(opt, i);
if (tmp == 2)
flag++;
else if (tmp == 1)
flag--;
if (!flag)
return set(opt, i, 2);
}
return -1;
}
void init() {
pow3[0] = 1;
for (int i = 1; i < N; i++)
pow3[i] = pow3[i - 1] * 3;
scanf("%d%d", &n, &m);
now = 0;
for (int i = 0; i < n; i++) {
scanf("%s", g[i]);
for (int j = 0; j < m; j++)
if (g[i][j] == ‘.‘)
final = i * m + j;
}
enqueue(0,0,1);
}
void solve() {
now ^= 1;
for (int i = 0; i < n; i++)
for (int j = 0; j < m; j++) {
for (int k = 1, l = cnt[now ^ 1]; k <= l; k++) {
int opt = Q[now ^ 1][k].opt;
long long sum = Q[now ^ 1][k].sum;
int left = get(opt, m), up = get(opt, j);
if (g[i][j] == ‘*‘) {
if (left == 0 && up == 0)
enqueue(opt, j, sum);
continue;
}
//论文中的情况1
if (left == 0 && up == 0) {
enqueue(set(set(opt, m, 2), j, 1), j, sum);
}//论文中的情况2.1
else if (left == 1 && up == 1) {
int tmp = change1(opt, j);
enqueue(set(set(tmp, m, 0), j, 0), j, sum);
}//论文中的情况2.2
else if (left == 2 && up == 2) {
int tmp = change2(opt, j);
enqueue(set(set(tmp, m, 0), j, 0), j, sum);
}//论文中的情况2.3
else if (left == 1 && up == 2) {
if (i * m + j == final)
enqueue(set(set(opt, m, 0), j, 0), j, sum);
}//论文中的情况2.4
else if (left == 2 && up == 1) {
enqueue(set(set(opt, m, 0), j, 0), j, sum);
} //论文中的情况3
else if (left == 0 || up == 0) {
enqueue(set(set(opt, m, 0), j, left + up), j, sum);
enqueue(set(set(opt, j, 0), m, left + up), j, sum);
}
}
now ^= 1;
for(int k = 1, t = cnt[now]; k <= t; k++)
state[now][Q[now][k].opt] = 0;
cnt[now] = 0;
}
printf("%lld\n", Q[now ^ 1][state[now ^ 1][0]].sum);
}
int main() {
init();
solve();
return 0;
}
版权声明:本文为博主原创文章,未经博主允许不得转载。
时间: 2024-10-12 02:36:45