在很多情况下,我们需要记录的状态很复杂。
我们就把这些dp统一称为状压dp。
这类问题的一个经典应用是在棋盘上。
我们往往记录一整行信息,或者记录之前的一些网格/线/列/斜线的信息。
在一些其他的问题中,我们可能需要记录每一项的选择状态。
我们通常用 0 表示一个物品没被选中,1 表被选中。
剩下的物体最优解,只与前面少量的信息有关。
在更复杂的情况下,一个项目可以有更复杂的状态。
一般用一个二进制数表示压缩后的状态。
然后即可暴力跑状态dp。
因此状压dp复杂度一般是指数级的。
所以 n 一般在 10 到 18 之间。
- 有 n 个猪,你可以从原点引出抛物线,问最少用多少次可以打到所有猪。
-
预处理所有有效抛物线。
-
以猪有没有被打下来作为状态进行状压DP。
我们对每个猪进行一次遍历,每次对序号在他后面的猪进行遍历,对于之前没有的抛物线我们新保存一次。
对于抛物线 y=ax2+bx+c。已知经过原点,所以 c=0。
我们又另知抛物线经过两点 (xi,yi) (xj,yj)。
可算出 a=xjyi−xiyjxixj(xi−xj), b=xixiyj−xjxjyixixj(xi−xj)、
因为 n≤18,所以很容易想到状压DP。
我们定义 fs 为打到 s 的状态时最少的次数。
对于每个抛物线,可易得转移方程 fi|linej=minfi|linej,fi+1。
不要忘记 f0=1 。
本题运用基本数学知识和基本状压DP,偏模板型。
时间复杂度 O(2n×n2)。
先简单介绍一个问题类型。
最小斯坦纳树:在一张给定的带权无向图中,将其中 k 个点变成连通块最少需要花费的代价。
因为最后连起来会是一棵树,所以就叫最小斯坦纳树。
令 fi,S 表示当前 i 在的连通块中,点集状态为 S 需要花费的最小费用。
我们需要合并不同的若干子集。
fi,S1|S2=min(fi,S1|S2)
需要一个SPFA实现。
fj,S|wj=min(fi,S+wi,j)
回归本题。
不妨先用上述方法求出每个子集汇合需要的代价。
最后的解是若干个子集的并。
每个子集都是若干种完整的颜色。
利用一个子集dp完成。
(注:这题没写代码,且偏口胡,应该思路什么都没锅)
代码不咕了 它有了/cy/qiang
我们找到一些边,使得构成欧拉回路。
那么就产生两个条件。
-
所有点度数都是偶数。
-
选出来的边构成的图,必须只有一个联通分量。
令 fi,S 表示当前每个点的状态,以及当前最后停留在 i 的位置。
S 状态每个点分成三种情况。
0:不与 1 连通
1:和 1 连通且度数为奇数
2:和 1 连通且度数为偶数
然而这样无法处理强制选边。
因此我们继续分析题目性质。
观察到所有边可以分成两部分。
一部分是到过的到没到过的点,另一部分是连接两个到过的点。
对于两个到过的点,连边即可改变他们的奇偶性。
且若走最短路径,一定会得到最好的效果。
我们猜想,可dp出所有点连通性的状态,然后我们再用最短路把奇数点之间两两连上。
令 fS 表示每个点与1号点连通状态确定时最小代价。
每次我们枚举边 (i,j) 其中 i 在 S 中不为0,j 为0。
第一次加进一个点的时候,附加上它使用必须边的连通性,即可把必须取边条件放上。
令 wi 表示只用 k 条边,i 和哪些点连通,且这些点奇偶状态如何。
我们在第一次加入连通块中的一个点时,我们就把所有点拖进去。
再令 gS 表示当 S 中点为奇数时,变成偶数的最优解。
每次枚举点转移即可qwq。
时间复杂度 O(3n×m),可能需要一些常数优化(¿)。
对子集枚举的复杂度进行一点分析。
这里的子集枚举为,在一个二进制数中,枚举所有为1的子集。
我们有一种通用写法。
这个写法看似很暴力实际上也很暴力,复杂度 O(3n)。
实际上就是 ∑ni=0C(n,i)×2i 展开后同 (1+2)n。
即为 O(3n)。
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const ll N=15,K=80,INF=0x3f3f3f3f;
ll n,m,sum,ans=INF;
ll hd[N],pw[N]={1},g[1<<N],dis[N][N],f[1600000],de[N],a[N];
struct edge{
ll t,nxt,l;
}es[K<<2];
queue<ll> q;
template <typename T> void rd(T &x){
ll fl=1;x=0;char c=getchar();
for(;!isdigit(c);c=getchar()) if(c=='-') fl=-fl;
for(;isdigit(c);c=getchar()) x=(x<<3)+(x<<1)+c-'0';
x*=fl;
}
void wr(ll x){
if(x<0) x=-x,putchar('-');
if(x<10) putchar(x+'0');
if(x>9) wr(x/10),putchar(x%10+'0');
}
void add(ll u,ll v,ll w){es[++sum]=(edge){v,hd[u],w};hd[u]=sum;}
int main(){
rd(n);rd(m);
memset(dis,INF,sizeof(dis));memset(g,INF,sizeof(g));memset(f,INF,sizeof(f));
for(ll i=1;i<=n;i++) dis[i][i]=0;
for(ll i=1;i<=n;i++) pw[i]=pw[i-1]*3;
for(ll i=0,u,v,w;i<m;i++){
rd(u);rd(v);rd(w);
dis[u][v]=dis[v][u]=min(dis[u][v],w);
de[u]++;de[v]++;
add(u,v,w);add(v,u,w);
}
rd(m);
for(ll i=0,u,v,w;i<m;i++){rd(u);rd(v);rd(w);dis[u][v]=dis[v][u]=min(dis[u][v],w);}
for(ll i=1;i<=n;i++)
for(ll j=1;j<=n;j++)
for(ll k=1;k<=n;k++) dis[i][j]=min(dis[i][j],dis[i][k]+dis[k][j]);
g[0]=0;
for(ll i=0;i<(1<<n);i++)
for(ll j=1;j<=n;j++)
if(!(i&(1<<(j-1))))
for(ll k=j+1;k<=n;k++)
if(!(i&(1<<(k-1)))) g[i^(1<<(j-1))^(1<<(k-1))]=min(g[i^(1<<(j-1))^(1<<(k-1))],g[i]+dis[j][k]);
f[2]=0;q.push(2);
while(!q.empty()){
ll qwq=q.front(),cnt=0;q.pop();
for(ll i=1;i<=n;i++) if(qwq/pw[i-1]%3>0) a[++cnt]=i;
for(ll i=1;i<=n;i++)
if(qwq/pw[i-1]%3==0){
for(ll j=hd[i];j;j=es[j].nxt)
if(qwq/pw[es[j].t-1]%3>0){
ll s=qwq+pw[i-1]*2;
if(f[qwq]>=f[s]) continue;
if(f[s]>=INF) q.push(s);
f[s]=f[qwq];
}
for(ll j=1;j<=cnt;j++){
ll s=qwq+pw[i-1];
s+=(qwq/pw[a[j]-1]%3==1)?pw[a[j]-1]:-pw[a[j]-1];
if(f[qwq]+dis[i][a[j]]>=f[s]) continue;
if(f[s]>=INF) q.push(s);
f[s]=f[qwq]+dis[i][a[j]];
}
}
}
for(ll k=0;k<pw[n];k++){
ll fl=0,nw=k,s=0;
for(ll i=1;i<=n;i++) if(de[i]&&k/pw[i-1]%3==0){fl=1;break;}
if(fl) continue;
for(ll i=1;i<=n;i++) if(de[i]&1) nw+=(k/pw[i-1]%3==1)?pw[i-1]:-pw[i-1];
for(ll i=1;i<=n;i++) if(nw/pw[i-1]%3==1) s^=1<<(i-1);
ans=min(ans,f[k]+g[s]);
}
for(ll i=1;i<=sum;i+=2) ans+=es[i].l;
wr(ans);puts("");
return 0;
}
__EOF__
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· .NET Core 中如何实现缓存的预热?
· 从 HTTP 原因短语缺失研究 HTTP/2 和 HTTP/3 的设计差异
· AI与.NET技术实操系列:向量存储与相似性搜索在 .NET 中的实现
· 基于Microsoft.Extensions.AI核心库实现RAG应用
· Linux系列:如何用heaptrack跟踪.NET程序的非托管内存泄露
· TypeScript + Deepseek 打造卜卦网站:技术与玄学的结合
· Manus的开源复刻OpenManus初探
· .NET Core 中如何实现缓存的预热?
· 三行代码完成国际化适配,妙~啊~
· 阿里巴巴 QwQ-32B真的超越了 DeepSeek R-1吗?