您的位置:首页 > 其它

URAL 1519 Formula 1

2012-04-18 21:12 323 查看
URAL_1519

插头dp的处女作终于完成啦^_^

具体的思路还是参考陈丹琦的论文吧,我也只是处于学习和模仿的阶段。我是仿照胡浩博客用最小表示法敲的代码,更多和插头dp相关的内容可以参考胡浩的博客:http://www.notonlysuccess.com/index.php/plug-dp-complete/

#include<stdio.h>
#include<string.h>
#define MAXD 15
#define HASH 30007
#define SIZE 1000010
int N, M, maze[MAXD][MAXD], code[MAXD], ch[MAXD], ex, ey;
char b[MAXD];
struct Hashmap
{
int size, head[HASH], next[SIZE];
long long f[SIZE], state[SIZE];
void init()
{
memset(head, -1, sizeof(head));
size = 0;
}
void push(long long st, long long ans)
{
int i, h = st % HASH;
for(i = head[h]; i != -1; i = next[i])
if(state[i] == st)
{
f[i] += ans;
return ;
}
state[size] = st, f[size] = ans;
next[size] = head[h];
head[h] = size ++;
}
}hm[2];
void decode(int *code, int m, long long st)
{
int i;
for(i = m; i >= 0; i --)
{
code[i] = st & 7;
st >>= 3;
}
}
long long encode(int *code, int m)
{
int i, cnt = 1;
long long st = 0;
memset(ch, -1, sizeof(ch));
ch[0] = 0;
for(i = 0; i <= m; i ++)
{
if(ch[code[i]] == -1)
ch[code[i]] = cnt ++;
code[i] = ch[code[i]];
st <<= 3;
st |= code[i];
}
return st;
}
void init()
{
int i, j, k;
memset(maze, 0, sizeof(maze));
ex = 0;
for(i = 1; i <= N; i ++)
{
scanf("%s", b + 1);
for(j = 1; j <= M; j ++)
if(b[j] == '.')
maze[ex = i][ey = j] = 1;
}
}
void shift(int *code, int m)
{
int i;
for(i = m; i > 0; i --)
code[i] = code[i - 1];
code[0] = 0;
}
void dpblank(int i, int j, int cur)
{
int k, t, left, up;
for(k = 0; k < hm[cur].size; k ++)
{
decode(code, M, hm[cur].state[k]);
left = code[j - 1], up = code[j];
if(left && up) // case 1
{
if(left == up)
{
if(i == ex && j == ey)
{
code[j - 1] = code[j] = 0;
if(j == M)
shift(code, M);
hm[cur ^ 1].push(encode(code, M), hm[cur].f[k]);
}
}
else
{
code[j - 1] = code[j] = 0;
for(t = 0; t <= M; t ++)
if(code[t] == up)
code[t] = left;
if(j == M)
shift(code, M);
hm[cur ^ 1].push(encode(code, M), hm[cur].f[k]);
}
}
else if(left) // case 2
{
if(maze[i][j + 1])
{
code[j - 1] = 0, code[j] = left;
hm[cur ^ 1].push(encode(code, M), hm[cur].f[k]);
}
if(maze[i + 1][j])
{
code[j - 1] = left, code[j] = 0;
if(j == M)
shift(code, M);
hm[cur ^ 1].push(encode(code, M), hm[cur].f[k]);
}
}
else if(up) // case 3
{
if(maze[i][j + 1])
{
code[j - 1] = 0, code[j] = up;
hm[cur ^ 1].push(encode(code, M), hm[cur].f[k]);
}
if(maze[i + 1][j])
{
code[j - 1] = up, code[j] = 0;
if(j == M)
shift(code, M);
hm[cur ^ 1].push(encode(code, M), hm[cur].f[k]);
}
}
else // case 4
{
if(maze[i][j + 1] && maze[i + 1][j])
{
code[j - 1] = code[j] = 13;
hm[cur ^ 1].push(encode(code, M), hm[cur].f[k]);
}
}
}
}
void dpblock(int i, int j, int cur)
{
int k;
for(k = 0; k < hm[cur].size; k ++)
{
decode(code, M, hm[cur].state[k]);
code[j - 1] = code[j] = 0;
if(j == M)
shift(code, M);
hm[cur ^ 1].push(encode(code, M), hm[cur].f[k]);
}
}
void solve()
{
int i, j, cur = 0;
long long ans = 0;
hm[cur].init();
hm[cur].push(0, 1);
for(i = 1; i <= N; i ++)
for(j = 1; j <= M; j ++)
{
hm[cur ^ 1].init();
if(maze[i][j])
dpblank(i, j, cur);
else
dpblock(i, j, cur);
cur ^= 1;
}
for(i = 0; i < hm[cur].size; i ++)
ans += hm[cur].f[i];
printf("%lld\n", ans);
}
int main()
{
while(scanf("%d%d", &N, &M) == 2)
{
init();
if(ex == 0)
printf("0\n");
else
solve();
}
return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: