洛谷P1312(Noip2011 D1T3)
一道大模拟题,
d
f
s
dfs
dfs时注意剪枝:
- 相同颜色的方块可以跳过
- 只有右边有方块才 M o v e Move Move,左边没有方块才 M o v e Move Move( i − 1 i-1 i−1列时将其右移,和你在 i i i列时左移是等效的)
#include <bits/stdc++.h>
using namespace std;
#define ll long long
#define inc(i,l,r) for (int i = l; i <= r; ++i)
const int N = 10;
template <typename T>
void read(T &x)
{
x = 0; ll f = 1; char ch = getchar();
while (!isdigit(ch)) {if(ch == '-') f = -1; ch = getchar();}
while (isdigit(ch)) x = (x<<3) + (x<<1) + ch - '0', ch = getchar();
x *= f;
}
int n;
int mp[N][N], mark[N][N], last[N][N][N], ans[N][5];
void Copy(int x) {
inc(i,1,5) inc(j,1,7) last[x][i][j] = mp[i][j];
}
void Back(int x) {
inc(i,1,5) inc(j,1,7) mp[i][j] = last[x][i][j];
ans[x][1] = ans[x][2] = ans[x][3] = -1;
}
void drop() {
inc(i,1,5) {
int x = 0;
inc(j,1,7) {
if (!mp[i][j]) x++;
else {
if (!x) continue;
mp[i][j-x] = mp[i][j];
mp[i][j] = 0;
}
}
}
}
bool update() {
int f = 0;
inc(i,1,5) {
inc(j,1,7) {
if (i >= 2 && i <= 4 && mp[i-1][j] == mp[i][j] && mp[i][j] == mp[i+1][j] && mp[i][j]) {
mark[i-1][j] = mark[i][j] = mark[i+1][j] = 1;
f = 1;
}
if (j >= 2 && j <= 6 && mp[i][j-1] == mp[i][j] && mp[i][j] == mp[i][j+1] && mp[i][j]) {
mark[i][j-1] = mark[i][j] = mark[i][j+1] = 1;
f = 1;
}
}
}
if (!f) return 0;
inc(i,1,5) {
inc(j,1,7) {
if (mark[i][j]) {
mark[i][j] = 0;
mp[i][j] = 0;
}
}
}
return 1;
}
void Move(int i, int j, int x) {
int tmp = mp[i][j];
mp[i][j] = mp[i+x][j];
mp[i+x][j] = tmp;
drop();
while (update()) drop();
}
bool check() {
inc(i,1,5) if (mp[i][1]) return false;
return true;
}
void dfs(int x) {
if (check()) {
inc(i,1,n) {
inc(j,1,3) printf("%d ", ans[i][j]);
puts("");
}
exit(0);
}
if (x == n + 1) return;
Copy(x);
inc(i,1,5) {
inc(j,1,7) {
if (mp[i][j]) {
if (i <= 4 && mp[i][j] != mp[i+1][j]) {
Move(i,j,1);
ans[x][1] = i - 1, ans[x][2] = j - 1, ans[x][3] = 1;
dfs(x + 1);
Back(x);
}
if (i >= 2 && !mp[i-1][j]) {
Move(i,j,-1);
ans[x][1] = i - 1, ans[x][2] = j - 1, ans[x][3] = -1;
dfs(x + 1);
Back(x);
}
}
}
}
}
int main()
{
int x;
read(n);
inc(i,1,5) {
inc(j,1,8) {
read(x);
if (!x) break;
mp[i][j] = x;
}
}
memset(ans, -1, sizeof(ans));
dfs(1);
puts("-1");
return 0;
}
hdu 4801
2013
2013
2013年区域赛的一道题目, 模拟二阶魔方, 每个面为平面旋转,有逆时针和顺时针两种, 六个面,
6
∗
2
=
12
6*2=12
6∗2=12种操作,然后,我们考虑相对的两个面, 一共只有
6
6
6种操作,用数组表示这
6
6
6种操作后的结果. 这个题目最多转
7
7
7次,那么一共有
6
7
=
279936
6^7=279936
67=279936种状态, 可以直接
d
f
s
dfs
dfs暴搜求出最多能还原的面
#include <iostream>
#include <cstdio>
using namespace std;
int mp[25];
int n, ans, cnt;
//{0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23}
int d[7][25] = {
{0, 1, 8, 14, 4, 3, 7, 13, 17, 9, 10, 2, 6, 12, 16, 15, 5, 11, 18, 19, 20, 21, 22, 23},//前左
{0, 1, 11, 5, 4, 16, 12, 6, 2, 9, 10, 17, 13, 7, 3, 15, 14, 8, 18, 19, 20, 21, 22, 23},//前右
{1, 3, 0, 2, 23, 22, 4, 5, 6, 7, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 9, 8},//上右
{2, 0, 3, 1, 6, 7, 8, 9, 23, 22, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 5, 4},//上左
{6, 1, 12, 3, 5, 11, 16, 7, 8, 9, 4, 10, 18, 13, 14, 15, 20, 17, 22, 19, 0, 21, 2, 23},//左上
{20, 1, 22, 3, 10, 4, 0, 7, 8, 9, 11, 5, 2, 13, 14, 15, 6, 17, 12, 19, 16, 21, 18, 23},//左下
};
void dfs(int cur, int *a)
{
cnt = 0;
if (a[0] == a[1] && a[0] == a[2] && a[0] == a[3]) cnt++;
if (a[4] == a[5] && a[4] == a[10] && a[4] == a[11]) cnt++;
if (a[6] == a[7] && a[6] == a[12] && a[6] == a[13]) cnt++;
if (a[8] == a[9] && a[8] == a[14] && a[8] == a[15]) cnt++;
if (a[16] == a[17] && a[16] == a[18] && a[16] == a[19]) cnt++;
if (a[20] == a[21] && a[20] == a[22] && a[20] == a[23]) cnt++;
if(cnt > ans)
ans = cnt;
if (cur == 0 || ans == 6) return;
int b[25];
for (int i = 0; i < 6; ++i) {
for (int j = 0; j < 24; ++j) {
b[j] = a[d[i][j]];
}
dfs(cur - 1, b);
}
}
int main()
{
while (~scanf("%d", &n)) {
ans = 0;
for (int i = 0; i < 24; ++i) {
scanf("%d", &mp[i]);
}
dfs(n, mp);
printf("%d\n", ans);
}
return 0;
}