洛谷P3956 [NOIp2017]棋盘
来源:互联网 发布:大数据世界txt下载 编辑:程序博客网 时间:2024/04/20 08:01
分析
在考场上乱搞了个DP……- 首先我们可以知道,这里的施展魔法实际上就相当于从一个有颜色的方块走到另一个与其距离为2的有颜色的方块
- 那么由于这题盲目地往下和往右走显然没有正确性,我一开始的想法是设
f[k][i][j] 表示走了k 步到方块(i,j) 所花费的最少金币,转移就是从一个点走到另一个点加上花费的金币,不过这样的时空复杂度都有些难以承受…… - 但我们可以发现:所有的“行走”显然都是在有颜色的方块之间进行
- 于是我们可以就给所有有颜色的方块编号,设
f[k][i] 表示走了k 步到编号为i 的方块所花费的最少金币,接着预先把所有距离为1和2的成对有颜色的方块存下来,直接在转移中使用即可 - 这样
f 数组不用开很大,时空复杂度就比较优秀了 出了考场后才发现建个图跑个最短路就没了……
代码
#include <iostream>#include <cstdio>#include <cstring>using namespace std;const int Maxn = 0x3f3f3f3f;const int N = 1005;const int dx[] = {1, -1, 0, 0}, dy[] = {0, 0, 1, -1};int f[N][N], a[N][N], x[N], y[N], z[N];int n, m, pN, qN, Ans = Maxn;struct Link{ int x, y, z;}p[N << 4], q[N << 4];inline void CkMin(int &x, int y){ if (x > y) x = y;}inline int Abs(int x){ return x < 0 ? -x : x;}inline int Tag(int x, int y){ return x != y ? 1 : 0;}inline void Init(){ for (int i = 1; i <= n; ++i) for (int j = 1; j <= n; ++j) if (i != j) { int tmp = Abs(x[i] - x[j]) + Abs(y[i] - y[j]); if (tmp == 1) { ++pN; p[pN].x = i; p[pN].y = j; p[pN].z = Tag(a[x[i]][y[i]], a[x[j]][y[j]]); } else if (tmp == 2) { ++qN; int dx = a[x[i]][y[i]], dy = a[x[j]][y[j]]; q[qN].x = i; q[qN].y = j; q[qN].z = Tag(dx, 0) + Tag(dy, 0) + 2; CkMin(q[qN].z, Tag(dx, 1) + Tag(dy, 1) + 2); } }}int main(){// freopen("chess.in", "r", stdin);// freopen("chess.out", "w", stdout); scanf("%d%d", &m, &n); for (int i = 1; i <= m; ++i) for (int j = 1; j <= m; ++j) a[i][j] = -1; for (int i = 1; i <= n; ++i) { scanf("%d%d%d", &x[i], &y[i], &z[i]); a[x[i]][y[i]] = z[i]; } if (a[1][1] == -1) { puts("-1"); fclose(stdin); fclose(stdout); return 0; } Init(); memset(f, Maxn, sizeof(f)); for (int i = 1; i <= n; ++i) if (x[i] == 1 && y[i] == 1) { f[1][i] = 0; break; } int lim = 1000; CkMin(lim, m * m); for (int k = 1; k < lim; ++k) { for (int i = 1; i <= pN; ++i) if (f[k][p[i].y] != Maxn) CkMin(f[k + 1][p[i].x], f[k][p[i].y] + p[i].z); for (int i = 1; i <= qN; ++i) if (f[k][q[i].y] != Maxn) for (int j = 0; j <= 1; ++j) CkMin(f[k + 2][q[i].x], f[k][q[i].y] + q[i].z); } if (a[m][m] != -1) { for (int i = 1; i <= n; ++i) if (x[i] == m && y[i] == m) { for (int k = m + m - 1; k <= lim; ++k) CkMin(Ans, f[k][i]); break; } } else //如果方块(m,m)无色要另外处理 { for (int i = 1; i <= n; ++i) if (x[i] + y[i] == m + m - 1) for (int k = m + m - 2; k <= lim; ++k) CkMin(Ans, f[k][i] + 2); } printf("%d\n", Ans == Maxn ? -1 : Ans);// fclose(stdin); fclose(stdout); return 0;}
阅读全文
1 0
- 洛谷P3956 [NOIp2017]棋盘
- 【NOIP2017】【Luogu P3956】【SPFA】棋盘
- 【NOIP2017】棋盘
- [NOIP2017普及组]棋盘
- 【NOIP2017普及组】棋盘
- [反思]NOIP2017棋盘
- [NOIP2017普及组]T3棋盘
- NOIP2017普及组★棋盘
- NOIP2017棋盘(普及T3)
- [NOIP2017普及组]——棋盘
- 【NOIP2017普及组正式赛】棋盘
- 【jzoj5306】【NOIP2017提高A组模拟8.18】【棋盘游戏】
- 洛谷P3960 [NOIp2017]列队
- noip2017
- NOIP2017
- noip2017
- NOIP2017
- NOIP2017
- armsd 指令详解
- 17.11.24,web学习第十一天,还有一年,努力吧青年
- memcpy
- 分蛋糕(2017年3月第一题)
- css中的字体尺寸
- 洛谷P3956 [NOIp2017]棋盘
- Titanic生还率预测
- LAMP环境搭建与配置(八)
- RabbitMQ入门教程(五):扇形交换机发布/订阅(Publish/Subscribe)
- LAMP环境搭建与配置(九)
- 京东强大数据支撑着618和双11
- 数组指针,指针数组,函数指针,等理解
- C语言基础操作符整理~
- fpt配置