题意:
投放炸弹,十字形伤害,会获取覆盖范围内有鱼的池塘的一条鱼
题解:
四进制枚举池塘中鱼的状态,二进制表示池塘中有没有鱼,然后状压枚举
代码:
#pragma GCC optimize("O3")
#include<iostream>
#include<algorithm>
#include <cstring>
#include <set>
//#define int long long
#define endl '\n'
using namespace std;
typedef pair<int, int> pii;
const int M = 1010;
const int N = 1048576 + 10;
const int INF = 1e9;
inline int read()
{
int x = 0, f = 1;
char ch = getchar();
while (ch < '0' || ch>'9')
{
if (ch == '-')
f = -1;
ch = getchar();
}
while (ch >= '0' && ch <= '9')
x = x * 10 + ch - '0', ch = getchar();
return x * f;
}
void write(int x)
{
if (x < 0)
putchar('-'), x = -x;
if (x > 9)
write(x / 10);
putchar(x % 10 + '0');
return;
}
int n, m, k, a[M][M], p[11], b[55], f[N];
int xd[5] = { 0,1,0,-1,0 }, yd[5] = { 0,0,1,0,-1 };
set<pii>st;
void slove()
{
n = read();
m = read();
k = read();
p[0] = 1;
for (int i = 1; i < k; i++) p[i] = p[i - 1] * 4;
for (int i = 1; i <= n; i++)
{
for (int j = 1; j <= m; j++)
{
a[i][j] = -1;
}
}
int ed = 0;
for (int i = 0; i < k; i++)
{
int x, y, z;
x = read();
y = read();
z = read();
ed += z * p[i];//ed表示四进制状态的终点
a[x][y] = i;
for (int j = 0; j < 5; j++)
{
int xx = x + xd[j], yy = y + yd[j];
if (xx <= 0 || xx > n || yy <= 0 || yy > m) continue;
st.insert({ xx, yy });//存放有意义的可炸点
}
}
int idx = 0;
for (auto [x, y] : st)
{
for (int j = 0; j < 5; j++)
{
int xx = x + xd[j];
int yy = y + yd[j];
if (xx <= 0 || xx > n || yy <= 0 || yy > m) continue;
if (a[xx][yy] != -1) b[idx] |= (1 << (a[xx][yy]));//炸这个可炸点会炸到哪几个有鱼的池塘,用二进制表示
}
idx++;
}
f[0] = 0;
for (int i = 1; i <= ed; i++) f[i] = INF;//状压枚举状态
for (int i = 1; i <= ed; i++)
{
int wal = 0;
for (int j = 0; j < k; j++)
{
if ((i / p[j]) & 3) wal |= (1 << j);//i中每两位表示j这个池塘中鱼的数量,wal表示第j个池塘还有没有鱼
}
for (int kezha = 0; kezha < idx; kezha++)//枚举炸哪个可炸点
{
int u = b[kezha] & wal;
if (u == 0) continue;
int now = 0;
for (int j = 0; j < k; j++)//枚举该池塘会不会被炸
{
if (u & (1 << j)) now += p[j] * max(0, ((i / p[j]) & 3) - 1);//如果炸到就将该池塘鱼-1加到当前状态
else now += p[j] * max(0, ((i / p[j]) & 3));//否则加上原来的数量
}
f[i] = min(f[i], f[now] + 1);
}
}
write(f[ed]);
}
signed main()
{
// ios::sync_with_stdio(0);
// cin.tie(0);
// cout.tie(0);
int t = 1;
// cin>>t;
while (t--)
slove();
return 0;
}