ZOJ3352【记忆化搜索】
2017-02-17 20:27
239 查看
先膜拜watashi!
前言:
比赛的时候,确定的是这是一个博弈,然后就是各种瞎猜,后面想到DP[ x ][ y ]代表x表白色的状态,y表黑色的状态,无果。挂机开始。GG、巨菜。
思路:
这一发记忆化搜索真是玄学。
仔细想想,首先我只要求权值最大,我不在乎输赢。
直接就是dp[i][j][k]代表当前白在 i 位置,黑在 j 位置,k为当前局势的赌资,dp存整个子结构包括本身的最大值。
然后记忆化搜索一发就可以了,很神奇。
记忆化搜索独有的味道:当前位置的状态为之前(其实是之后?)最优状态的转化(前身?)。
这里还有一点就是在搜的连续两步,其实分成了两个人的行为,所有当前的最大为之后那个人赢的相反数。(他赢即我输)
watashi美丽code:(小引用好酷)
#include <cstdio>
#include <vector>
#include <cstring>
using namespace std;
const int MAXN = 52;
const int INF = 65536;
int d[MAXN];
vector<int> e[MAXN];
int b[MAXN][MAXN][MAXN * 4];
int c[MAXN][MAXN][MAXN * 4];
int gao(int x, int y, int z) {
if (c[x][y][100 + z] != -1) {
return b[x][y][100 + z];
}
int tmp;
int &ret = b[x][y][100 + z], &cnt = c[x][y][100 + z];
ret = (e[x].empty() && e[y].empty()) ? -z : -INF;
cnt = 1;
for (vector<int>::const_iterator i = e[x].begin(); i != e[x].end(); ++i) {
tmp = -gao(*i, y, z + d[*i]);
if (tmp > ret) {
ret = tmp;
cnt = 1;
} else if (tmp == ret) {
++cnt;
}
}
for (vector<int>::const_iterator i = e[y].begin(); i != e[y].end(); ++i) {
tmp = -gao(x, *i, z - d[*i]);
if (tmp > ret) {
ret = tmp;
cnt = 1;
} else if (tmp == ret) {
++cnt;
}
}
return ret;
}
int main() {
int n, m, x, y, s, t;
while (scanf("%d%d%d%d", &n, &m, &x, &y) != EOF) {
for (int i = 0; i < n; ++i) {
scanf("%d", &d[i]);
e[i].clear();
}
for (int i = 0; i < m; ++i) {
scanf("%d%d", &s, &t);
e[s].push_back(t);
}
memset(c, 0xff, sizeof(c));
gao(x, y, 1);
printf("%d %d\n", b[x][y][101], c[x][y][101]);
}
return 0;
}
//Run ID Submit Time Judge Status Problem ID Language Run Time(ms) Run Memory(KB) User Name Admin
//584 2010-07-16 19:50:54 Accepted 1074 C++ 860 4572 anotherpeg Source
前言:
比赛的时候,确定的是这是一个博弈,然后就是各种瞎猜,后面想到DP[ x ][ y ]代表x表白色的状态,y表黑色的状态,无果。挂机开始。GG、巨菜。
思路:
这一发记忆化搜索真是玄学。
仔细想想,首先我只要求权值最大,我不在乎输赢。
直接就是dp[i][j][k]代表当前白在 i 位置,黑在 j 位置,k为当前局势的赌资,dp存整个子结构包括本身的最大值。
然后记忆化搜索一发就可以了,很神奇。
记忆化搜索独有的味道:当前位置的状态为之前(其实是之后?)最优状态的转化(前身?)。
这里还有一点就是在搜的连续两步,其实分成了两个人的行为,所有当前的最大为之后那个人赢的相反数。(他赢即我输)
watashi美丽code:(小引用好酷)
#include <cstdio>
#include <vector>
#include <cstring>
using namespace std;
const int MAXN = 52;
const int INF = 65536;
int d[MAXN];
vector<int> e[MAXN];
int b[MAXN][MAXN][MAXN * 4];
int c[MAXN][MAXN][MAXN * 4];
int gao(int x, int y, int z) {
if (c[x][y][100 + z] != -1) {
return b[x][y][100 + z];
}
int tmp;
int &ret = b[x][y][100 + z], &cnt = c[x][y][100 + z];
ret = (e[x].empty() && e[y].empty()) ? -z : -INF;
cnt = 1;
for (vector<int>::const_iterator i = e[x].begin(); i != e[x].end(); ++i) {
tmp = -gao(*i, y, z + d[*i]);
if (tmp > ret) {
ret = tmp;
cnt = 1;
} else if (tmp == ret) {
++cnt;
}
}
for (vector<int>::const_iterator i = e[y].begin(); i != e[y].end(); ++i) {
tmp = -gao(x, *i, z - d[*i]);
if (tmp > ret) {
ret = tmp;
cnt = 1;
} else if (tmp == ret) {
++cnt;
}
}
return ret;
}
int main() {
int n, m, x, y, s, t;
while (scanf("%d%d%d%d", &n, &m, &x, &y) != EOF) {
for (int i = 0; i < n; ++i) {
scanf("%d", &d[i]);
e[i].clear();
}
for (int i = 0; i < m; ++i) {
scanf("%d%d", &s, &t);
e[s].push_back(t);
}
memset(c, 0xff, sizeof(c));
gao(x, y, 1);
printf("%d %d\n", b[x][y][101], c[x][y][101]);
}
return 0;
}
//Run ID Submit Time Judge Status Problem ID Language Run Time(ms) Run Memory(KB) User Name Admin
//584 2010-07-16 19:50:54 Accepted 1074 C++ 860 4572 anotherpeg Source
相关文章推荐
- Zoj 1671 Walking Ant(BFS+优先队列||记忆化搜索)
- zoj 3211 dream city 贪心 dp和记忆化搜索
- ZOJ 3644 Kitty's Game dfs,记忆化搜索,map映射 难度:2
- ZOJ 3352-3361||Monthly July 2010
- ZOJ 3795 Grouping(强联通缩点,记忆化搜索)
- [ZOJ 3469]Food Delivery[记忆化搜索]
- ZOJ 2624 Popo's Lamps(DP 记忆化搜索)
- zoj 3644(dp + 记忆化搜索)
- zoj 3644(dp + 记忆化搜索)
- ZOJ 1227 Free Candies(记忆化搜索)
- ZOJ 3644 Kitty's Game (记忆化搜索+hash)
- ZOJ BCD Code 记忆化搜索+数位DP+AC自动机
- ZOJ 2922 Bombs(记忆化搜索)
- zoj 1530 记忆化搜索
- zoj 1107 FatMouse and Cheese(记忆化搜索)
- ZOJ 1107 FatMouse and Cheese(记忆化搜索)
- zoj 1107 FatMouse and Cheese(动态规划 记忆化搜索)
- FOJ/FZU/FZOJ 1550Monetary System【记忆化搜索】
- ZOJ 1107 FatMouse and Cheese(记忆化搜索)
- [ZOJ 3352] Boring Board Game [动态规划]