您的位置:首页 > 其它

状态压缩DP

2017-03-22 21:12 162 查看
首先,我们以一道状压经典题TSP来引入。

TSP问题

一张图上有n个点,给定相应的邻接矩阵,需要求出从0号节点出发,经过且只经过每个顶点一次,最后仍回到0号节点的最小边权。

思路:假设现在已访问过的顶点集合(起点0当作还未访问过的顶点)为s,当前所在顶点为v,用dp[s][v]表示从v出发访问剩余的所有顶点,最终回到顶点0的路径的权值总和的最小值。由于从v出发可以移到任意一个节点u∉s,因此

dp[V][0]=0

dp[s][v]=min{dp[s∪{u}][u]+d(v,u)}

我们只要按照这个递推式进行计算即可。对于集合我们可以把每一个元素的选取与否对应到一个二进制位里,从而把状态压缩成一个整数,方便了计算和维护。

核心代码如下:

//input
int n;
int d[maxn][maxn];
int dp[1<<maxn][maxn];
int rec(int s,int v)
{
if(dp[s][v]>=0)
{
return dp[s][v];
}
if(s== (1<<n)-1 && v==0)
//若已经访问过所有节点且回到0号点
{
return dp[s][v]=0;
}
int res=inf;
for(int u=0;u<n;u++)
{
if(!(s>>u &1))//若顶点u没走过
{
res=min(res,rec(s|1<<u,u)+d[v][u]);
}
}
return dp[s][v]=res;
void solve()
{
memset(dp,-1,sizeof(dp));
printf("%d\n",rec(0,0));
}

}


## 状压 ##解法需要保存一定的状态数据,每个状态数据通常情况下是可以通过2进制来表示的。这就要求状态数据的每个单元只有两种状态,比如说棋盘上的格子,放棋子或者不放,或者是硬币的正反两面。这样就可以用0或者1来表示状态数据的每个单元,而整个状态数据就是一个0、1组成的二进制数。

接下来,我们再看一道题。

题目大意:输入n和m表示一个n*m的矩形,用1*2的方块进行覆盖,不能重叠,不能越出矩形边界,问完全覆盖完整个矩形有多少种不同的方案。

思路稍后添加…………
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: