前言
第三道大模拟,写篇题解庆祝一下。
文中粗体字是我踩坑的地方,欢迎统计我被坑了多少次。
思路
终局奖分很简单,放在主函数里,所以我们看每次的操作是怎样的。
首先判断操作不合法:
- 给定的坐标超出范围。
- 是空位置。
- 不是相邻的。
- 交换后仍然不合法。
注意不合法要把交换的东西复原。然后我们合法的话就一直操作,不合法了就跳出,跑下一次。
这里大家可以参考我的顺序:
- 统计主颜色,满了就看牌型奖分。
- 一直跑。先连通块统计组合奖分。
- 消除,包括特殊属性。消除的时候统计消除奖分。注意这里只标记不删除。
- 现在再删除。
- 自由掉落。
- 循环结束了。统计连锁奖分。
大部分操作还是比较简单的,比较恶心的操作就是牌型奖分。
首先我们统计的时候把主函数用 Node 存储。存储的颜色显然不能重复。
Node tmp = (Node){-114514, -114514};
for (int i = 1; i <= n; i++)
for (int j = 1; j <= m; j++)
if (del[i][j])
{
if (tmp.x == -114514) tmp.x = color[i][j];
else if (tmp.y != color[i][j] && tmp.y == -114514) tmp.y = color[i][j];
}
card[++cntcard] = tmp;
if (cntcard == 5)
{
vector <int> empty; //没有任何意义的玩意,他是空的
maxn = 0, dfs(1, empty);
ans += maxn;
cntcard = 0;
}
现在满五个了,直接枚举跳颜色 1 还是颜色 2 即可。
#define let(x) tmp.push_back(x), dfs(i + 1, tmp), tmp.pop_back()
void dfs(int i, vector <int> tmp)
{
if (i > 5) {maxn = max(maxn, calc(tmp)); return;}
if (card[i].x != -114514) let(card[i].x);
if (card[i].y != -114514) let(card[i].y);
}
至于计算就比较简单了(但是判断较多,脑子不清醒最好不要做)。元素只有五个,所以用任何办法统计都可以,显然不会超时。
代码
这次打大模拟激进了一点,所以就没写多少注释,但是看懂很容易的吧(
#include <iostream>
#include <cstdio>
#include <cmath>
#include <cstring>
#include <vector>
#include <algorithm>
//这两个是关键字,所以就替换掉,代码中没有影响
#define y1 jojojo
#define round jinitaimei
using namespace std;
#define squ(x) ((x) * (x))
const int N = 55, dict[4][2] = {{0, 1}, {0, -1}, {1, 0}, {-1, 0}};
int n, m, k, q, color[N][N], tag[N][N];
void swp(int x1, int y1, int x2, int y2) {swap(color[x1][y1], color[x2][y2]), swap(tag[x1][y1], tag[x2][y2]);}
bool near(int x1, int y1, int x2, int y2)
{
for (int i = 0; i < 4; i++)
if (x1 + dict[i][0] == x2 && y1 + dict[i][1] == y2 || x2 + dict[i][0] == x1 && y2 + dict[i][1] == y1)
return true;
return false;
}
struct Node {int x, y;};
bool del[N][N];
bool chk()
{
memset(del, false, sizeof del);
bool flag = false;
for (int x = 1; x <= n; x++)
for (int y = 1; y <= m; y++)
for (int i = 0; i < 4; i++)
{
int dx = x + dict[i][0], dy = y + dict[i][1], ddx = dx + dict[i][0], ddy = dy + dict[i][1];
if (dx < 1 || dx > n || dy < 1 || dy > m) continue;
if (ddx < 1 || ddx > n || ddy < 1 || ddy > m) continue;
if (color[x][y] != 0 && color[x][y] == color[dx][dy] && color[x][y] == color[ddx][ddy])
del[x][y] = del[dx][dy] = del[ddx][ddy] = flag = true;
}
return flag;
}
bool vis[N][N]; int siz;
void dfs(int x, int y)
{
siz++, vis[x][y] = true;
for (int i = 0; i < 4; i++)
{
int dx = x + dict[i][0], dy = y + dict[i][1];
if (dx < 1 || dx > n || dy < 1 || dy > m) continue;
if (del[dx][dy] && color[x][y] == color[dx][dy] && !vis[dx][dy]) dfs(dx, dy);
}
}
int ans, round;
void remove(int x, int y)
{
if (color[x][y] == 0 || vis[x][y]) return;
vis[x][y] = true, ans += round * color[x][y];
if (tag[x][y] == 1 || tag[x][y] == 3) {for (int i = 1; i <= m; i++) remove(x, i);}
if (tag[x][y] == 2 || tag[x][y] == 3) {for (int i = 1; i <= n; i++) remove(i, y);}
if (tag[x][y] == 4)
{
for (int i = max(1, x - 1); i <= min(n, x + 1); i++)
for (int j = max(1, y - 1); j <= min(m, y + 1); j++)
remove(i, j);
}
else if (tag[x][y] == 5)
{
for (int i = max(1, x - 2); i <= min(n, x + 2); i++)
for (int j = max(1, y - 2); j <= min(m, y + 2); j++)
remove(i, j);
}
else if (tag[x][y] == 6)
{
for (int i = 1; i <= n; i++)
for (int j = 1; j <= m; j++)
if (color[i][j] == color[x][y])
remove(i, j);
}
}
void drop()
{
for (int i = n; i; i--)
for (int j = 1; j <= m; j++)
if (color[i][j] == 0)
for (int ii = i - 1; ii; ii--)
if (color[ii][j] != 0)
{
swp(i, j, ii, j);
break;
}
}
Node card[105]; int cntcard;
int calc(vector <int> v)
{
int cntbox[105] = {}; vector <int> cnt[10];
for (int x : v) cntbox[x]++;
for (int i = 0; i < 105; i++) cnt[cntbox[i]].push_back(i);
for (int i = 0; i < 10; i++) sort(cnt[i].begin(), cnt[i].end());
if ((int)cnt[1].size() == 5) return 50 + cnt[1][4];
if ((int)cnt[1].size() == 3 && (int)cnt[2].size() == 1) return 100 + cnt[2][0] * 2;
if ((int)cnt[1].size() == 1 && (int)cnt[2].size() == 2) return 200 + cnt[2][1] * 2 + cnt[2][0];
if ((int)cnt[1].size() == 2 && (int)cnt[3].size() == 1) return 300 + cnt[3][0] * 3;
if ((int)cnt[2].size() == 1 && (int)cnt[3].size() == 1) return 500 + cnt[3][0] * 3 + cnt[2][0];
if ((int)cnt[1].size() == 1 && (int)cnt[4].size() == 1) return 750 + cnt[4][0] * 5;
if ((int)cnt[5].size() == 1) return 1000 + cnt[5][0] * 10;
return 0;
}
int maxn;
#define let(x) tmp.push_back(x), dfs(i + 1, tmp), tmp.pop_back()
void dfs(int i, vector <int> tmp)
{
if (i > 5) {maxn = max(maxn, calc(tmp)); return;}
if (card[i].x != -114514) let(card[i].x);
if (card[i].y != -114514) let(card[i].y);
}
void play()
{
Node tmp = (Node){-114514, -114514};
for (int i = 1; i <= n; i++)
for (int j = 1; j <= m; j++)
if (del[i][j])
{
if (tmp.x == -114514) tmp.x = color[i][j];
else if (tmp.x != color[i][j] && tmp.y == -114514) tmp.y = color[i][j];
}
card[++cntcard] = tmp;
if (cntcard == 5)
{
vector <int> empty;
maxn = 0, dfs(1, empty);
ans += maxn;
//printf("mx = %d\n", maxn);
cntcard = 0;
}
for (round = 1;; round++)
{
memset(vis, false, sizeof vis);
for (int i = 1; i <= n; i++)
for (int j = 1; j <= m; j++)
if (del[i][j] && !vis[i][j])
siz = 0, dfs(i, j), ans += 50 * squ(siz - 3);
memset(vis, false, sizeof vis);
for (int i = 1; i <= n; i++)
for (int j = 1; j <= m; j++)
if (del[i][j] && !vis[i][j])
remove(i, j);
for (int i = 1; i <= n; i++)
for (int j = 1; j <= m; j++)
if (vis[i][j])
color[i][j] = 0;
drop();
// system("cls");
// printf("当前%d局势\n", round);
// for (int i = 1; i <= n; i++, putchar('\n'))
// for (int j = 1; j <= m; j++)
// printf("(%d,%d) ", color[i][j], tag[i][j]);
// system("pause");
if (!chk()) break;
}
ans += 80 * squ(round - 1);
// printf("奖金 %d\n", ans);
}
bool solve(int x1, int y1, int x2, int y2)
{
if (x1 < 1 || x1 > n || y1 < 1 || y1 > m) return false;
if (x2 < 1 || x2 > n || y2 < 1 || y2 > m) return false;
if (color[x1][y1] == 0 || color[x2][y2] == 0 || !near(x1, y1, x2, y2)) return false;
swp(x1, y1, x2, y2);
if (chk()) {play(); return true;}
else {swp(x1, y1, x2, y2); return false;} //不成功要换回来!
}
int main()
{
scanf("%d%d%d%d", &n, &m, &k, &q);
for (int i = 1; i <= n; i++)
for (int j = 1; j <= m; j++)
scanf("%d", &color[i][j]);
for (int i = 1; i <= n; i++)
for (int j = 1; j <= m; j++)
scanf("%d", &tag[i][j]);
int allOK_score = 1000, wonderful_score = 10000;
while (q--)
{
int x1, y1, x2, y2;
scanf("%d%d%d%d", &x1, &y1, &x2, &y2);
if (!solve(x1, y1, x2, y2)) allOK_score = 0;
}
for (int i = 1; i <= n && wonderful_score; i++)
for (int j = 1; j <= m && wonderful_score; j++)
if (color[i][j] != 0)
wonderful_score = 0;
cout << ans + allOK_score + wonderful_score;
return 0;
}
希望能帮助到大家!
标签:cnt,return,int,题解,color,P8422,y1,y2 From: https://www.cnblogs.com/liangbowen/p/17151985.html