状态压缩学习笔记
使用计算机中二进制的特性,将一个难以表达的状态,一般为有或没有(
枚举
状压 dp
定义
枚举每一种状态
比如
形式化地,本题状态转移方程就是:
实现时还要注意
#include<bits/stdc++.h>
using namespace std;
const int N = 16;
int n;
double a[N][N];
double x[N],y[N];
double dp[N][1<<N],ans=1e100;
int main() {
cin>>n;
for(int i=1;i<=n;i++) {
cin>>x[i]>>y[i];
}
memset(dp,0x7f,sizeof dp);
for(int i=0;i<=n;i++) {
for(int j=0;j<=n;j++) {
a[i][j]=sqrt((x[j]-x[i])*(x[j]-x[i])+(y[j]-y[i])*(y[j]-y[i]));
}
}
for(int i=1;i<=n;i++) {
dp[i][1<<i-1]=a[0][i];//初始化
}
for(int i=0;i<1<<n;i++) {//状态
for(int j=0;j<=n;j++) {//到哪
if((i&(1<<j-1))==0) continue;
//该点没走过
for(int k=0;k<=n;k++) {//在哪
if(((i&(1<<k-1))==0) | (k==j)) continue;
dp[j][i]=min(dp[j][i],dp[k][i-(1<<j-1)]+a[j][k]);
}
}
}
for(int i=1;i<=n;i++) {
ans=min(ans,dp[i][(1<<n)-1]);//将所有的都走过一遍了
}
printf("%.2lf",ans);
return 0;
}
状压最短路
有时候,使用 dp 具有后效性,此时要考虑与其他知识结合起来。
比如最短路算法。
写完 dp 后就发现,关灯的顺序不同,结果也不相同,就会涉及到重复转移,即后效性。
求问题的最优解还有最短路算法。每次进行关灯操作的代价均为
枚举进行的操作(类似边),利用单调性,看当前序列变成了什么(类似到达的点),如果是第一次,那就入队。
发现,总共有
#include<bits/stdc++.h>
using namespace std;
const int N = 11,M = 101;
int n,m;
int a[M][N];//选择了第 m 种,最后状态为 n
int ck(int k,int l) {//按照题意模拟
for(int i=1;i<=n;i++) {
if(a[k][i]==1 && (l&(1<<i-1)))
l-=(1<<i-1);
if(a[k][i]==-1 && ((l&(1<<i-1))==0))
l+=(1<<i-1);
}
return l;
}
int vis[1<<N];
int main() {
cin>>n>>m;
for(int i=1;i<=m;i++) {
for(int j=1;j<=n;j++) {
cin>>a[i][j];
}
}
memset(vis,-1,sizeof vis); vis[(1<<n)-1]=0;
queue<int>q; q.push((1<<n)-1);
while(!q.empty()) {
int x=q.front(); q.pop();
for(int j=1;j<=m;j++) {
int l1=ck(j,x);
if(vis[l1]==-1) vis[l1]=vis[x]+1, q.push(l1);
if(l1==0) {
cout<<vis[l1];
return 0;
}
}
}
cout<<-1;
return 0;
}
本文作者:cjrqwq
本文链接:https://www.cnblogs.com/yfzqwq/p/18492779
版权声明:本作品采用知识共享署名-非商业性使用-禁止演绎 2.5 中国大陆许可协议进行许可。
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 分享一个免费、快速、无限量使用的满血 DeepSeek R1 模型,支持深度思考和联网搜索!
· 基于 Docker 搭建 FRP 内网穿透开源项目(很简单哒)
· ollama系列1:轻松3步本地部署deepseek,普通电脑可用
· 按钮权限的设计及实现
· 25岁的心里话