洛谷 P1433 吃奶酪
状态压缩,和剪枝
最优化剪枝:如果距离大于当前最短距离,则必然不最优 。
如果当前连通块到某点的距离大于之前记录的距离,则该走法不最优。(dp[i][j]实现)
状态压缩:用二进制的每一位表示某个点是否访问过,例如第一个点访问过则二进制第一位为1.
首先我们在状态中有一个 当前到了数组哪个点的状态,命名为nowdot。每次定义p为当前点到第i个的距离,用二进制保存,初始化为int p = nowdot + (1 << (i - 1)),如果从p到i的距离已经有过更新并且本次构造的距离还大于之前,则跳过;否则更新,继续搜索。
#include <iostream>
#include <cstdio>
#include <cmath>
using namespace std;
const int N = 20;
int n;
double ans = 1e9, dp[66000][20]; //dp[i][j]i表示压缩的状态表示走过的点,j表示当前状态最后到达的一个点
struct node {
double x;
double y;
}a[N];
double discal (int l, int m) { //距离计算函数
return sqrt((a[l].x - a[m].x) * (a[l].x - a[m].x)
+ (a[l].y - a[m].y) * (a[l].y - a[m].y));
}
bool vis[N];//点标记,防止重复访问
//dfs(已经吃了多少个,当前吃的第几个,当前跑了多远,当前走过的点状态)
void dfs(int sum, int nowi, double dis, int nowdot) {
//最优化剪枝,如果距离大于当前最短距离,则必然不最优
if (dis > ans) {
return;
}
//搜索正常结束条件
if (sum == n) {
if (dis < ans) ans = dis;
return;
}
for (int i = 1; i <= n; i++) {
if (!vis[i]) {
int p = nowdot + (1 << (i - 1));
//二进制状态压缩从当前点到这个点
if (dp[p][i] != 0 && dp[p][i] <= dis + discal(nowi, i))
continue;
vis[i] = 1;//标记防止重复访问
dp[p][i] = dis + discal(nowi, i);
dfs(sum + 1, i, dp[p][i], p);
vis[i] = 0;//取消标记
}
}
}
int main() {
cin >> n;
for (int i = 1; i <= n; i++) {
cin >> a[i].x >> a[i].y;
}
dfs(0, 0, 0, 0);
printf("%.2lf", ans);
return 0;
}
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· TypeScript + Deepseek 打造卜卦网站:技术与玄学的结合
· 阿里巴巴 QwQ-32B真的超越了 DeepSeek R-1吗?
· 如何调用 DeepSeek 的自然语言处理 API 接口并集成到在线客服系统
· 【译】Visual Studio 中新的强大生产力特性
· 2025年我用 Compose 写了一个 Todo App
2017-07-24 数字(number)
2017-07-24 寻找最美的你(select)
2017-07-24 木棍
2017-07-24 lowbit