P3943 星空 题解
题目链接
分析
题目中的区间反转,相当于区间异或
对于区间操作,我们可以想到差分
对本题来说,我们可以做一次异或差分
也就是
这样以后,对于
每次操作,我们一定会贪心的让其中一个点为
所以可以用
考虑到 差分后
然后就做完了
代码
#include<bits/stdc++.h> using namespace std; const int N=500004,INF=0x3f3f3f3f; int n,k,m,ma=0; int ta[N]; int a[40],tot=-1;//记录为0的灯的位置 int mov[200]; int f[1<<22]; int cost[200][200]; queue<int>q; int dis[N]; bool vis[N]; void bfs(int x){ memset(vis,0,sizeof(vis)); memset(dis,0x3f,sizeof(dis)); q.push(a[x]);vis[a[x]]=1;dis[a[x]]=0; while(!q.empty()){ int u=q.front(); q.pop(); for(int i=1;i<=m;i++){ if(u+mov[i]<=n&&!vis[u+mov[i]]){ dis[u+mov[i]]=dis[u]+1; vis[u+mov[i]]=1; q.push(u+mov[i]); } if(u-mov[i]>=1&&!vis[u-mov[i]]){ dis[u-mov[i]]=dis[u]+1; vis[u-mov[i]]=1; q.push(u-mov[i]); } } } for(int i=0;i<=tot;i++) cost[x][i]=dis[a[i]]; } int main(){ scanf("%d %d %d", &n, &k, &m);n++; for(int i=1;i<=k;i++){int x;scanf("%d", &x);ta[x]=1;} for(int i=1;i<=m;i++){scanf("%d", &mov[i]);ma=max(ma,mov[i]);} for(int i=1;i<=n;i++) if(ta[i]!=ta[i-1]) a[++tot]=i;//差分 for(int i=0;i<=tot;i++) bfs(i); int lim=(1<<(tot+1))-1;//状压DP for(int i=0;i<lim;i++) f[i]=INF; for(int i=lim-1;i>=0;i--){ for(int p1=0;p1<=tot;p1++){ if((i>>p1)&1) continue; for(int p2=p1+1;p2<=tot;p2++){ if((i>>p2)&1) continue; f[i]=min(f[i],f[i^(1<<p1)^(1<<p2)]+cost[p1][p2]); } } } // if(f[0]==INF) cout<<-1<<endl; else printf("%d\n", f[0]); return 0; }
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 地球OL攻略 —— 某应届生求职总结
· 周边上新:园子的第一款马克杯温暖上架
· Open-Sora 2.0 重磅开源!
· 提示词工程——AI应用必不可少的技术
· .NET周刊【3月第1期 2025-03-02】