首页 > 其他分享 >P1433 吃奶酪 标签: 动态规划,dp | 状态压缩

P1433 吃奶酪 标签: 动态规划,dp | 状态压缩

时间:2023-03-10 22:35:31浏览次数:86  
标签:return int double 奶酪 P1433 result xc yc dp

详见:https://www.luogu.com.cn/problem/P1433
就不写基础原理了,直接看注释吧

点击打开非map版
#include <iostream>
#include <cstdio>
#include <cmath>
#include <algorithm>

using namespace std;

int all, n;
double ans = 200000000;

struct point {
	double x, y;
} a[100];

double dp[1 << 15][20] = {};

int lowbit(int x) {
	return x & (-x);
}

// 快速log2 很巧妙的思路 
int log2_fast(int n) {  
    int result = 0;  
    if(n&0xffff0000) { result += 16; n >>= 16; }  
    if(n&0x0000ff00) { result += 8; n >>= 8; }  
    if(n&0x000000f0) { result += 4; n >>= 4; }  
    if(n&0x0000000c) { result += 2; n >>= 2; }  
    if(n&0x00000002) { result += 1; n >>= 1; }  
    return result; 
}

double gougu(point x, point y) {
	double xc, yc;
	xc = abs(x.x - y.x);
	yc = abs(x.y - y.y);
	return sqrt(xc*xc+yc*yc);
}

// 用引用节省内存,假设递归次数较多这个是重要的!!! 
void dfs(double di, int state, point& be) {
	// 剪枝优化 
	if(di >= ans) {
		return;
	}
	// 判断结束 
	if(state == all) {
		// 选择最优 
		ans = min(di, ans);
		return;
	}
	// 解析状压,转换为二进制其实使用 int vis = all - state; 效果也是一摸一样的 
	int vis = all&(~state);
	for(int i=vis; i; i -= lowbit(i)) {
		int x = lowbit(i);
		// 转换为数组下标 
		int j = log2_fast(x);
		// 求出给下一个深搜的参数 
		int nextState = state+x;
		double nextdi = di+gougu(be, a[j]);
		// 剪枝,很简单的道理,这条路走了,就不走了
		// 记录成double的原因是就算当前坐在的节点和状态相同,走的距离也可以不相同,所以需要更多的信息作比较  
		if(dp[nextState][j]!=0 && dp[nextState][j]<=nextdi) {
			continue;
		}
		// 记录 
		dp[nextState][j] = nextdi;
		// 接着深搜 
		dfs(nextdi, nextState, a[j]);
	}
}

int main() {
	// 初始化 
	dis.clear();
	cin >> n;
	all = (1<<n)-1;
	for(int i = 0; i<n; i++) {
		cin >> a[i].x >> a[i].y;
	}
	point t;
	t.x = t.y = 0; 
	// 深搜的参数有三个,分别为距离,状压后的是否使用和当前点
	dfs(0, 0, t);
	printf("%.2f", ans);
	return 0;
}
/**
 * 本程序使用了map来,记忆化勾股定理的数,map很慢,会超时,实测不使用map来存储也可以过 
 * 非要用map的话就吸氧罢(O2),吸氧后的和不吸氧的普通的差不多耗时
 **/
#include <iostream>
#include <cstdio>
#include <cmath>
#include <algorithm>
#include <map>

using namespace std;

int all, n;
double ans = 200000000;

struct point {
	double x, y;
} a[100];

map<pair<double, double>, double> dis;

double dp[1 << 15][20] = {};

int lowbit(int x) {
	return x & (-x);
}

// 快速log2 很巧妙的思路 
int log2_fast(int n) {  
    int result = 0;  
    if(n&0xffff0000) { result += 16; n >>= 16; }  
    if(n&0x0000ff00) { result += 8; n >>= 8; }  
    if(n&0x000000f0) { result += 4; n >>= 4; }  
    if(n&0x0000000c) { result += 2; n >>= 2; }  
    if(n&0x00000002) { result += 1; n >>= 1; }  
    return result; 
}

double gougu(point x, point y) {
	// 算差,利用差来记忆数据 
	double xc, yc;
	xc = abs(x.x - y.x);
	yc = abs(x.y - y.y);
	if(xc > yc) {
		swap(xc, yc);
	}
	pair<double, double> t(xc, yc);
	if(dis[t] != 0) {
		return dis[t];
	}
	return dis[t] = sqrt(xc*xc+yc*yc);
}

// 用引用节省内存,假设递归次数较多这个是重要的!!! 
void dfs(double di, int state, point& be) {
	// 剪枝优化 
	if(di >= ans) {
		return;
	}
	// 判断结束 
	if(state == all) {
		// 选择最优 
		ans = min(di, ans);
		return;
	}
	// 解析状压,转换为二进制其实使用 int vis = all - state; 效果也是一摸一样的 
	int vis = all&(~state);
	for(int i=vis; i; i -= lowbit(i)) {
		int x = lowbit(i);
		// 转换为数组下标 
		int j = log2_fast(x);
		// 求出给下一个深搜的参数 
		int nextState = state+x;
		double nextdi = di+gougu(be, a[j]);
		// 剪枝,很简单的道理,这条路走了,就不走了
		// 记录成double的原因是就算当前坐在的节点和状态相同,走的距离也可以不相同,所以需要更多的信息作比较  
		if(dp[nextState][j]!=0 && dp[nextState][j]<=nextdi) {
			continue;
		}
		// 记录 
		dp[nextState][j] = nextdi;
		// 接着深搜 
		dfs(nextdi, nextState, a[j]);
	}
}

int main() {
	// 初始化 
	dis.clear();
	cin >> n;
	all = (1<<n)-1;
	for(int i = 0; i<n; i++) {
		cin >> a[i].x >> a[i].y;
	}
	point t;
	t.x = t.y = 0; 
	// 深搜的参数有三个,分别为距离,状压后的是否使用和当前点
	dfs(0, 0, t);
	printf("%.2f", ans);
	return 0;
}

写这篇题解的时候运气太背啦!!!

先是luogu爆网关,然后博客园爆网关
感觉最近互联网不太平啊
image
image

标签:return,int,double,奶酪,P1433,result,xc,yc,dp
From: https://www.cnblogs.com/dffxd/p/17204836.html

相关文章

  • CentOS 7 部署 HDP 3.3.1
    一、环境服务器名称配置IP地址备注hdp-161-1418核/16G内存/300GSSD硬盘10.32.161.141MGR/Agenthdp-161-1428核/16G内存/300GSSD硬盘10.32.161.142Age......
  • 2023,最新wordpress建站教程
    在我们购买了虚拟主机之后,我们要如何用wordpress去搭建一个满足自己需求的网站呢?这篇文章就来详细讲一讲,用wordpress搭建一个网站的具体过程。1.购买域名并完成解析选择......
  • 高性能、低功耗4口全速 USB1.1 HUB控制器DPU54 替代AU9254
    产品概述DPU54是一款高性能、低功耗4口全速USB1.1HUB控制器,上行端口兼容全速12MHz模式,4个下行端口兼容全速12MHz、低速1.5MHz两种模式。DPU54采用状态机单事务处......
  • MFC-GetWindowThreadProcessId获取指定窗口线程ID和进程ID
     HWNDhWnd=::FindWindow(NULL,_T("sss.txt-记事本"));DWORDdwTID=0;DWORDdwPID=NULL;dwTID=::GetWindowThreadProcessId(hWnd,&dwPID......
  • 最大正方形(二维dp)
    最大正方形在一个由'0'和'1'组成的二维矩阵内,找到只包含'1'的最大正方形,并返回其面积。示例1:输入:matrix=[["1","0","1","0","0"],["1","0","1","1","1"],[&quo......
  • VGA、HDMI、DP你都懂吗?显示接口大盘点
    电脑显示器,就像我们人类的眼睛一样,是我们和电脑之间进行信息交流的重要窗口。电脑显示器接口,则好比是我们人类的视神经,承载着传递信息的重要任务。随着科技与硬件的不断发......
  • D. Book of Evil(树的直径+换根dp)
    #include<bits/stdc++.h>#definedebug1(a)cout<<#a<<'='<<a<<endl;#definedebug2(a,b)cout<<#a<<"="<<a<<""<<#b<<"="<&......
  • TCP/UDP
    一、概述接着温顾TCP/UDP UDP(用户数据报):1.无连接2.不可靠传输协议3.传输速率比较快4.首部字段较少5.应用场景......
  • 【DP】LeetCode 剑指 Offer 10- I. 斐波那契数列
    题目链接剑指Offer10-I.斐波那契数列思路递推,思路可以参考剑指Offer10-II.青蛙跳台阶问题代码classSolution{publicintfib(intn){inta......
  • DP练习1题解
    这是2023.3.7DP题单十个题的题解。T1ColoredSubgraphs(CF1796E)简要题意:给定一棵树,你要对树进行链剖分,必须剖成上下竖直的链,求剖后最短链的长度最大值。最小值最大......