首页 > 其他分享 >模拟

模拟

时间:2023-07-14 19:35:28浏览次数:20  
标签:const point int double ans return 模拟

模拟

T1 4682 粒子运动

 因为题目数据不大,所以直接枚举两个点,看看哪两个点是距离最近的两个点。然后用一个结构体来存储点的坐标,然后里面的运算就和平面向量的计算是一样的。

 这里要注意的是这里的所有基本都是 \(double\) ,不要忘记了把结构体里面重载运算符的地方改成 \(double\) 。

 首先开始的时候我们先将所有点都平移一下,使圆心与原点重合。然后我们存粒子的时候,还预处理一下这个点距离下一次碰壁是什么时候,还有这个点移动完这一整个割线需要多久的时间。然后这个就用平面向量的数学知识来计算就可以了。然后这里还有一点叉乘没有学,没太看懂,找个时间问问小 \(S\) 好了。

 然后我们就枚举是哪两个点距离最近,在枚举的时候,我们再遍历每一次碰撞,因为每一次碰撞之间的运动状态都是相对固定的,所以可以直接计算。

 那个式子我找个时间看看打不打,我先贴一贴。

 每一次碰撞结束的时候,我们都看一看这一段之中这两个点的最近距离是多少然后更新一下答案,碰撞那里还用了一下二倍角公式和平面向量来求 \(sin\) 和 \(cos\) 的值。

 每一次碰撞结束后都改变一下这个点距离他的下次碰撞还要多久,因为这个角度是固定的,其实他就是走过对应的割线所需的时间,也就是前面存的那个值。然后还改变一下当前点的 \(cnt\) 值,就可以了。

 我愿称之为我在oi学数学

 还要注意的一点就是不要习惯性就用快读输入了, \(double\) 不能用快读!!

// 坐标的结构体
struct point{
	double x,y;
	point operator + (const point &t) const {
		// 加
		return {x + t.x,y + t.y};
	}
	point operator - () const {
		// 变成负的
		return {-x,-y};
	}
	point operator - (const point &t) const {
		// 减
		return *this + - t;
	}
	point operator * (const double &t) const {
		// 数乘
		return {x * t,y * t};
	}
	point operator / (const double &t) const {
		// 数除
		return {x / t,y / t};
	}
	double operator * (const point &t) const {
		// 点乘
		return x * t.x + y * t.y;
	}
	double operator % (const point &t) const {
		// 叉乘
		return x * t.y - y * t.x;
	}
	double lenf() { // 长度的平方
		return (*this) * (*this);
	}
	double len() { // 长度
		return sqrt((*this) * (*this));
	}
	void xuan(double cosa,double sina) { // 旋转a度
		(*this) = {x * cosa - y * sina,x * sina + y * cosa};
	}
	point dwxl() {
		return (*this) / (*this).len();
	}
	void read() {
		scanf("%lf%lf",&x,&y);
	}
};

struct node{
	point st; // start
	point v; // velocity
	double t,T; // 碰撞所需的时间,走过割线所需时间
	int cnt; // 碰撞次数
}w[N];

int n,k;
point ori;
double R;
double ans = dinf;

void fww(point a) {
	cout << a.x << ' ' << a.y << endl;
}

void init(node &t) {
	t.st = t.st - ori; // 平移到原点
	double v = t.v.len(); // 速率
	double d = fabs(t.st % t.v) / v;
	double len = sqrtl(R * R - d * d);
	t.T = 2 * len / v;
	t.t = (len + t.v.dwxl() * (-t.st)) / v;
}

void peng(node &t) { // 碰撞
	double len = t.st.len() * t.v.len();
	double bansin = t.st * t.v / len;
	double bancos = (t.st % t.v) / len;
	// 二倍角公式
	double sin = 2 * bansin * bancos;
	double cos = bancos * bancos - bansin * bansin;
	t.v.xuan(cos,sin);
}

void update(point ua,point ub,point va,point vb) {
	if ((ua - ub) * (vb - va) > 0 && (ua + va - ub - vb) * (va - vb) > 0)
		// 特判不相交
		ans = min(ans,fabs((ua - ub) % (vb - va)) / (vb - va).len());
	ans = min(ans,min((ua - ub).len(),(ua - ub + va - vb).len()));
}

void get(node a,node b) {
	double t; // 距离下次碰还有多久时间
	point dis1,dis2;
	while (a.cnt < k && b.cnt < k) {
		t = min(a.t,b.t);
		dis1 = a.v * t;
		dis2 = b.v * t;
		a.t -= t,b.t -= t;
		update(a.st,b.st,dis1,dis2);
		a.st = a.st + dis1,b.st = b.st + dis2;
		if (a.t < zero) peng(a),a.t = a.T,++ a.cnt;
		if (b.t < zero) peng(b),b.t = b.T,++ b.cnt;
	}
}

int main(){
	ori.read(),cin >> R;
	n = fr(),k = fr();
	for (int i = 1; i <= n; i ++) {
		w[i].st.read();
		w[i].v.read();
		init(w[i]);
	}
	for (int i = 1; i <= n; i ++) {
		for (int j = 1; j < i; j ++) {
			get(w[i],w[j]);
		}
	}
	printf("%.3lf",ans);
	return 0;
}

练习

 评价是 \(C\) 题是个烂题!

A.华容道

 这一题卡常卡的人要死了,还找了郭总和潇潇帮我卡常,后来把 \(dis\) 数组改掉了,然后把 \(piiii\) 改成了结构体之后过了。

 然后整体思路还是直接 \(bfs\) 爆搜,然后这个队列里面要存五个数(如果存四个数的话就会洛谷上面 \(TLE\) ,但是信友队上面可以过),五个数前面两个就是空白点的坐标,第三个和第四个就是目标点的坐标,第五个点就是用了多少步,如果这个单独存一个的话会 \(TLE\),有可能是因为一开始初始化的时候这个数组有一点打,或者什么别的。

 然后就是比较常规的 \(bfs\) ,要注意的就是更新目标点的判断。

 然后这里的手写循环队列是错误的!这题能过是因为这个队列是没有循环的,如果循环了的话那里要写 \(\ne\)

struct node{
	int a,b,c,d,e;
};

int n,m,Q;
bool w[N][N];
int bex,bey,enx,eny,kbx,kby;
int dx[4] = {1,0,-1,0};
int dy[4] = {0,1,0,-1};
bool flag[N][N][N][N];
vector<int> e[N * N];
node q[10000005];

int main(){
	n = fr(),m = fr(),Q = fr();
	for (int i = 1; i <= n; i ++) {
		for (int j = 1; j <= m; j ++) {
			w[i][j] = fr();
		}
	}
	while (Q --) {
		memset(flag,0,sizeof flag);
		kbx = fr(),kby = fr();
		bex = fr(),bey = fr();
		enx = fr(),eny = fr();
		if (bex == enx && bey == eny) {
			fw(0);
			ch;
			continue;
		}
		int hh = 0,tt = 0;
		q[0] = {kbx,kby,bex,bey,0};
		int dist;
		bool st = false;
		while (hh <= tt) {
			node t = q[hh ++];
			if (hh == 10000000) hh = 0;
			
			dist = t.e;
			
			for (int i = 0; i < 4; i ++) {
				int x = t.a + dx[i];
				int y = t.b + dy[i];
				if (!w[x][y]) continue;
				if (x > n || y > m || !x || !y) continue;
				int ux = t.c,uy = t.d;
				if (x == t.c && y == t.d) {
					ux = t.a,uy = t.b;
				}
				if (flag[x][y][ux][uy]) continue;
				flag[x][y][ux][uy] = true;
				if (ux == enx && uy == eny) {
					fw(dist + 1);
					ch;
					st = true;
					break;
				}
				if (tt == 10000000) tt = 0;
				q[++ tt] = {x,y,ux,uy,dist + 1};
			}
			if (st) break;
		}
		if(!st) wj;
	}
	return 0;
}

B.围栏问题

 这一题就是单纯的爆搜,这个爆搜的理论复杂度本来感觉应该是 \(16!\) 的,但是这里是可以过的,爆搜的复杂度就是玄学。然后这里优化的话就用了最优性优化,好像就没有什么别的优化了。

 下面那一大堆是我一开始没想到怎么爆搜的时候写的部分分代码,有点点长,但是可以拿 \(30\) 分部分分。

 然后爆搜的时候不 \(sort\) 也是可以过掉的,但是我是先写的 \(sort\) 再写的爆搜,所以就懒得删了。

int m,k,n;
pii w[N];
int dfn[N];
int maxx[N],may[N],mix[N],miy[N];
int ans;

bool cmp(pii a,pii b) {
	return a.se < b.se;
}

int get(int i) {
	return (maxx[i] - mix[i] + 1) * 2 + (may[i] - miy[i] + 1) *2;
}

void dfs(int u,int cnt,int sum) {
	if (sum > ans) return ;
	if (u > n) {
		ans = min(ans,sum);
		return ;
	}
	if (cnt > k) return ;
	int a,b,c,d;
	for (int i = 1; i <= cnt; i ++) {
		a = maxx[i],b = mix[i],c = may[i],d = miy[i];
		maxx[i] = max(maxx[i],w[u].fi);
		may[i] = max(may[i],w[u].se);
		miy[i] = min(miy[i],w[u].se);
		mix[i] = min(mix[i],w[u].fi);
		dfs(u + 1,cnt,sum - (a - b + 1) * 2 - (c - d + 1) * 2 + get(i));
		maxx[i] = a,mix[i] = b,may[i] = c,miy[i] = d;
	}
	if (cnt == k) return ;
	maxx[cnt + 1] = w[u].fi,mix[cnt + 1] = w[u].fi;
	may[cnt + 1] = w[u].se,miy[cnt + 1] = w[u].se;
	dfs(u + 1,cnt + 1,sum + 4);
	maxx[cnt + 1] = 0,mix[cnt + 1] = 0;
	may[cnt + 1] = 0,miy[cnt + 1] = 0;
}

int main(){
	m = fr(), k = fr(),n = fr();
	for (int i = 1; i <= n; i ++) {
		w[i].fi = fr();
		w[i].se = fr();
	}
	int maxx = 0,minx = m;
	int maxy = 0,miny = m;
	for (int i = 1; i <= n; i ++) {
		maxx = max(maxx,w[i].fi);
		maxy = max(maxy,w[i].se);
		minx = min(minx,w[i].fi);
		miny = min(miny,w[i].se);
	}
	if (k == 1) {
		fw((maxx - minx + 1) * 2 + (maxy - miny + 1) * 2);
		return 0;
	}
	sort(w + 1,w + 1 + n);
	if (k == 2) {
		int ans = inf;
		for (int i = 1; i <= n; i ++) {
			int t = 0;
			int maxx = 0,minx = m;
			int maxy = 0,miny = m;
			for (int l = 1; l <= i; l ++) {
				maxx = max(maxx,w[l].fi);
				maxy = max(maxy,w[l].se);
				minx = min(minx,w[l].fi);
				miny = min(miny,w[l].se);
			}
			t += (maxx - minx + 1) * 2 + (maxy - miny + 1) *2;
			maxx = 0,minx = m;
			maxy = 0,miny = m;
			for (int r = i + 1; r <= n; r ++) {
				maxx = max(maxx,w[r].fi);
				maxy = max(maxy,w[r].se);
				minx = min(minx,w[r].fi);
				miny = min(miny,w[r].se);
			}
			if (i != n) 
			t += (maxx - minx + 1) * 2 + (maxy - miny + 1) *2;
			ans = min(ans,t);
		}
		sort(w + 1,w + 1 + n,cmp);
		for (int i = 1; i <= n; i ++) {
			int t = 0;
			int maxx = 0,minx = m;
			int maxy = 0,miny = m;
			for (int l = 1; l <= i; l ++) {
				maxx = max(maxx,w[l].fi);
				maxy = max(maxy,w[l].se);
				minx = min(minx,w[l].fi);
				miny = min(miny,w[l].se);
			}
			t += (maxx - minx + 1) * 2 + (maxy - miny + 1) *2;
			maxx = 0,minx = m;
			maxy = 0,miny = m;
			for (int r = i + 1; r <= n; r ++) {
				maxx = max(maxx,w[r].fi);
				maxy = max(maxy,w[r].se);
				minx = min(minx,w[r].fi);
				miny = min(miny,w[r].se);
			}
			if (i != n) 
			t += (maxx - minx + 1) * 2 + (maxy - miny + 1) *2;
			ans = min(ans,t);
		}
		fw(ans);
		return 0;
	}
	ans = inf;
	dfs(1,0,0);
	fw(ans);
	return 0;
}

C.立体图

 这题是个烂题!!!不想多说,这题洛谷上面是黄色,但是我觉得这明明就是黑色!!模拟一生之敌!!

 回来后去洛谷讨论区捞了一个代码借鉴借鉴。

int n,m;
int h[N][N];
char wdwx[10][10] = {
	";;+---+",
	";/   /|",
	"+---+ |",
	"|   | +",
	"|   |/",
	"+---+",
};
char ans[5005][5005];
pii cfx[6005]; // 长方形坐标

void get(int i) {
	pii t = cfx[i];
	n = max(n,cfx[i].fi + 5);
	m = max(m,cfx[i].se + 6);
	for (int i = 0; i < 10; i ++) {
		for (int j = 0; j < 10; j ++) {
			if (wdwx[i][j] == '+' || wdwx[i][j] == '|' || 
				wdwx[i][j] == '/' || wdwx[i][j] == ' ' ||
				wdwx[i][j] == '-')
					ans[t.fi + i][t.se + j] = wdwx[i][j];
		}
	}
}

int main(){
	n = fr(),m = fr();
	for (int i = 1; i <= n; i ++) {
		for (int j = 1; j <= m; j ++) {
			h[i][j] = fr();
		}
	}
	memset(ans,'.',sizeof ans);
	int idx = 0;
	int yidong = 0;
	for (int i = 1; i <= n; i ++) {
		for (int j = 1; j <= m; j ++) {
			for (int k = 1; k <= h[i][j]; k ++) {
				cfx[++ idx].se = (j - 1) * 4 + (n - i) * 2 + 1;
				cfx[idx].fi = 1 + (i - 1) * 2 - (k - 1) * 3;
				yidong = max(yidong ,1 - cfx[idx].fi);
			}
		}
	}
	for (int i = 1; i <= idx; i ++) {
		cfx[i].fi += yidong;
		get(i);
	}
	for (int i = 1; i <= n; i ++) {
		for (int j = 1; j <= m; j ++) {
			cout << ans[i][j];
		}
		cout << endl;
	}
	return 0;
}

标签:const,point,int,double,ans,return,模拟
From: https://www.cnblogs.com/jingyu0929/p/17554805.html

相关文章

  • 2023冲刺国赛模拟 36.1
    最近越来越懒了,估了很长时间的题解,OI生涯结束前是凑不够200篇博客了,但退役前还是努力写点东西吧。第一次写题解的大约在暑假集训,原因是当时改模拟赛题目经常参考学长的博客,于是自己也尝试这写了博客;然而省选以后,改题就很少参考学长的博客,一个原因是很难找到模拟赛题目的题解,......
  • 【考后总结】7 月多校国赛模拟赛 3
    7.14冲刺国赛模拟36T1染色题关键性质是奇数偶数位上可以放置的只有两种,若\(i\)和\(i-2\)选的颜色不同,那么在\(i\)位置放一个球,\([l,r]\)的限制等价于\([l+2,r]\)中奇数位和偶数位不同时有球。设\(f_i\)为\(i\)放置一个球的合法方案数,这样直接枚举上一个球所在......
  • 冲刺国赛模拟 36
    感觉思想都不难,但是场上不是想不出来就是写不动,见了鬼了。染色题考虑一个转化:对于奇数位置,在\(a_i\neqa_{i+2}\)的地方放一个红球,对于偶数位置在同样的地方放个蓝球。这样每个区间的限制变成\([l,r-2]\)不能同时有红蓝球,转移前缀和优化一下即可。#include<iostream>#inc......
  • [总结]2023-7-13A组模拟赛
    [总结]2023-7-13A组模拟赛P1心路历程发现今天的题目描述很直接,比昨天的好懂。然后发现T2似乎是数据结构,好像找到了归宿,心里踏实了一点。之后就发现自己不会的计数题但是有两道:T1和T3。T4还以为是板子题,然后发现读不懂。于是就开始干T2(终于不是从T1开始做了!!!),一开始以为要用高级......
  • HBuilder X连接MuMu模拟器指南
    一、运行MuMu模拟器查看服务端口16384二、adb环境变量配置找到HBuilderX的安装路径,进入如下目录,获取adb路径配置环境变量path添加adb路径三、adb连接端口打开cmd或者powershell窗口,执行如下命令adbconnect127.0.0.1:16384四、运行到模拟器测试设置adb......
  • vue 模拟滚动条循环滚动
    <template><el-cardclass="card-duty"><template#header><divclass="card-header"><span>重大警情</span></div></template>......
  • H3C 模拟器 防火墙开启Web功能
    环境windows10,模拟器 HCL_V5.9.0防火墙 1在windows添加虚拟网卡我的电脑--管理--设备管理器--网络适配器(选择)--操作--(添加过时硬件)--进入向导-下一步--搜索并自动安装--选择网络适配器-2给虚拟网卡配置ip如上图中所示3在防火墙命令行配置<H3C>system-view[H3C......
  • 如何实现ios电脑模拟器的具体操作步骤
    iOS电脑模拟器在开发iOS应用程序时,我们通常需要在真实设备上进行测试和调试。然而,有时我们可能没有设备可用,或者我们希望在不同的iOS版本上进行测试,这时就需要使用iOS电脑模拟器了。什么是iOS电脑模拟器iOS电脑模拟器是一种可以在Mac电脑上运行的虚拟设备,它模拟了真实iOS设备的......
  • NOIP 2023 模拟赛 20230712 C 论剑
    首先是伟大的题面然后是数据范围先解决1-4号数据点1.枚举每个gcd的值p,统计一次答案,得到最小值(期望得分20)\[ans=\min_{p=2}^{\maxa}\sum^n_{i=1}\min(a_i\bmodp,p-(a_i\bmodp)(a>p))\]2.我们可以发现p仅在为质数时不会重复,也可以将p换为质数(期望得分40)两种的时间复......
  • HHHOJ #1238. 「NOIP 2023 模拟赛 20230712 D」但战斗还未结束 思考--zhengjun
    赛时想写60pts,结果cxr似乎少算了一点空间,导致我一直没把空间卡过去QWQ。当时不会dfs求拓扑序,这里讲一下。枚举所有非访问过的点依次dfs,每次进行下列操作:找出\(v\)的一个未访问过的入点\(u\),调用dfs(u);找不到\(u\)的时候,把\(v\)加入拓扑序列中。代码#inc......