2024.9.12
今日总结
1:OIer们的东方梦
经过读题可以发现这道题目是搜索的题目主要是需要考虑每个点的状态vis表示每个点的状态开三维数组,分别表示[有剑时][有花时][都没有]每个点是否访问过
其他的就是考虑细节就可以解决,还是比较基础的bfs题目
点击查看代码
#include<bits/stdc++.h>
using namespace std;
const int N = 1e6 + 10;
const int M = 1100;
int n,m,sx,sy,cnt;
int vis[5][M][M],gx[N],gy[N],it[5];
char mp[M][M],str[M];
int mx[4] = {0,1,0,-1};
int my[4] = {1,0,-1,0};
struct Node
{
int x,y,stp,lv;
bool operator<(const Node &x)const
{
return x.stp < stp;
}
};
priority_queue<Node> q;
inline void bfs()
{
Node pre,nxt;
pre.x = sx,pre.y = sy;
vis[0][sx][sy] = 0;
pre.stp = 0;
pre.lv = 0;
q.push(pre);
while(!q.empty())
{
pre = q.top();
q.pop();
for(int i = 0;i < 4;i ++)
{
nxt.x = pre.x + mx[i];
nxt.y = pre.y + my[i];
nxt.stp = pre.stp + 1;
nxt.lv = pre.lv;
if(nxt.x < 1 || nxt.x > n || nxt.y < 1 || nxt.y > m)
continue;
if(mp[nxt.x][nxt.y] == '1' && nxt.lv != 2)
continue;
else if(mp[nxt.x][nxt.y] == '2' && nxt.lv == 0)
nxt.stp += 3;
else if(mp[nxt.x][nxt.y] == '3' && nxt.lv == 0)
nxt.stp += 8;
else if(mp[nxt.x][nxt.y] == '4')
nxt.lv = max(nxt.lv,1);
else if(mp[nxt.x][nxt.y] == '5' && nxt.lv < 2)
{
q.push(nxt);
nxt.lv = 2;
nxt.stp += 5;
}
else if(mp[nxt.x][nxt.y] == 'E')
{
printf("%d\n",nxt.stp);
return;
}
if(!vis[nxt.lv][nxt.x][nxt.y])
{
vis[nxt.lv][nxt.x][nxt.y] = 1;
q.push(nxt);
}
if(mp[nxt.x][nxt.y] == 'X' && it[nxt.lv] == 0)
{
it[nxt.lv] = 1;
nxt.stp ++;
for(int i = 1;i <= cnt;i ++){
nxt.x = gx[i];
nxt.y = gy[i];
if(!vis[nxt.lv][nxt.x][nxt.y])
{
vis[nxt.lv][nxt.x][nxt.y] = 1;
q.push(nxt);
}
}
}
}
}
printf("We want to live in the TouHou World forever\n");
}
int main()
{
scanf("%d %d",&n,&m);
for(int i = 1;i <= n;i ++)
scanf("%s",&mp[i][1]);
for(int i = 1;i <= n;i ++)
{
for(int j = 1;j <= m;j ++)
{
if(mp[i][j] == 'S')
sx = i,sy = j;
if(mp[i][j] == 'X')
{
gx[++ cnt] = i;
gy[cnt] = j;
}
}
}
bfs();
return 0;
return 0;
}
2:ycz的妹子
这道题主要是树状数组+二分+模拟来做
点击查看代码
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const int N = 8e5 + 10;
int n,m,Max;
ll s;
ll a[N],b[N],sum[N];
inline int lowbit(int x)
{
return x & (-x);
}
inline void pushup(int r,int fa)
{
while(r <= 55000)
{
sum[r] += fa;
r += lowbit(r);
}
}
inline int check(int l)
{
int res = 0;
while(l > 0)
{
res += sum[l];
l -= lowbit(l);
}
return res;
}
inline int query(int l,int r,int k)
{
if(l == r) return l;
int mid = l + r >> 1;
if(check(mid) >= k)
return query(l,mid,k);
else return query(mid + 1,r,k);
}
int main()
{
scanf("%d %d",&n,&m);
for(int i = 1;i <= n;i ++)
{
scanf("%lld",&a[i]);
s += a[i];
pushup(i,1);
b[i] = 1;
}
Max = n;
while(m --)
{
char op[10];
scanf("%s",op + 1);
int x;
ll y;
if(op[1] == 'C')
{
scanf("%d %lld",&x,&y);
a[x] -= y;
s -= y;
}
else if(op[1] == 'I')
{
scanf("%d %lld",&x,&y);
if(b[x] == 0)
{
pushup(x,1);
b[x] = 1;
}
s-= a[x];
a[x] = y;
s += y;
Max = max(Max,x);
}
else if(op[1] == 'D')
{
scanf("%d",&x);
int pop = query(1,Max,x);
pushup(pop,-1);
b[pop] = 0;
s -= a[pop];
a[pop] = 0;
}
else printf("%lld\n",s);
}
return 0;
}
3:小奔关闹钟
考虑状压定义一个数组f,用于求解关掉第i个开关后,开关的变化情况.入数据时可以使用邻接表,然后使用双重循环遍历,遇到第i个开关就把第i位取反。然后用bfs走一遍最短路
点击查看代码
#include<bits/stdc++.h>
using namespace std;
const int N = 20;
int n;
int f[N];
bool a[N][N],vis[1 << N];
vector<int> v[N];
struct Node
{
int x,s;
}w;
queue<Node> q;
int bfs()
{
w = Node{(1 << n) - 1,0};
q.push(w);
while(!q.empty())
{
w = q.front();
if(w.x == 0) return w.s;
for(int i = 0;i < n;i ++)
{
int x = w.x ^ f[i];
if(vis[x]) continue;
vis[x] = 1;
q.push(Node{x,w.s + 1});
}
q.pop();
}
return -1;
}
int main()
{
scanf("%d",&n);
for(int i = 0;i < n;i ++)
a[i][i] = 1;
for(int i = 0;i < n;i ++)
{
int m,x;
scanf("%d",&m);
for(int j = 0;j < m;j ++)
{
scanf("%d",&x);
x --;
if(a[i][x] == 0)
{
a[i][x] = 1;
v[i].push_back(x);
}
}
}
for(int i = 0;i < n;i ++)
{
f[i] = (1 << i);
for(auto x : v[i])
{
f[i] ^= (1 << x);
for(auto y : v[x])
f[i] ^= (1 << y);
}
}
int res = bfs();
if(res == -1) printf("Change an alarm clock,please!");
else printf("%d",res);
return 0;
}