noip模拟66

Posted WindZR

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了noip模拟66相关的知识,希望对你有一定的参考价值。

考试过程:可能受到了自己生病的一些影响,这次考试状态不是很好。做题的时候比较困。我按顺序开题,首先是T1,这题挺有意思,显然是一道DP题,但是刚开始我想的是类似于\\(f_{i,j}\\)表示第1个序列选\\(i\\)个,第二个序列选\\(j\\)个的最大值,但是这么转移不仅复杂度很高并且转移也很麻烦。我又想了想觉得可以将两个序列分开考虑,最后再合并,反正只要体积是一定的就是对的,然后就切了。
T2,这题考场上实在没什么思路,就打了个暴搜。T3,我觉得部分分挺多,但是我读错题了,导致我获得了\\(0pts\\)的高分...。总之,以后还是要多注意身体,生病啥的都会影响考试状态。

T1 接力比赛

思路:上面说的差不多了,我将左右两边分开考虑,我的朴素DP是\\(f_{i,j}\\)表示第一个序列以\\(i\\)结尾的总体积为\\(j\\)的最大值,\\(g_{i,j}\\)同理,那么转移是显然的\\(f_{i,j}=max(f_{i,j},f_{k,j-w_i}+v_i)\\),这样的复杂度是\\(n^2\\times U\\)的,复杂度比较高,然后我观察这个DP式子,发现这好像是一个背包,然后我就按照背包DP的思路优化了一下\\(f_{i,j}=max(f_{i-1,j},f{i-1,j-w_i}+v_i)\\),这样就把复杂度降掉一个\\(n\\),然后卡卡上界这道题就切了。
代码如下:

AC_code

#include<bits/stdc++.h>
#define int long long
#define re register int
#define ii inline int
#define iv inline void
#define f() cout<<"fuck"<<endl
using namespace std;
const int N=1e6+10;
const int M=1010;
const int INF=1e18;
int n,m,ans;
int f[N],g[N],s1[N],s2[N];
struct node
{
	int w,v;
}c1[M],c2[M];
ii read()
{
	int x=0;char ch=getchar();bool f=1;
	while(ch<\'0\' or ch>\'9\')
	{
		if(ch==\'-\') f=0;
		ch=getchar();
	}
	while(ch>=\'0\' and ch<=\'9\')
	{
		x=(x<<1)+(x<<3)+(ch^48);
		ch=getchar();
	}
	return f?x:(-x);
}
signed main()
{
	freopen("game.in","r",stdin),freopen("game.out","w",stdout);
	n=read(),m=read();
	for(re i=1;i<=n;i++) c1[i]=(node){read(),read()},s1[i]=s1[i-1]+c1[i].w;
	for(re i=1;i<=m;i++) c2[i]=(node){read(),read()},s2[i]=s2[i-1]+c2[i].w;
	int up=max(s1[n],s2[m]);
	for(re i=1;i<=up;i++) f[i]=g[i]=-INF;
	f[c1[1].w]=c1[1].v;
	for(re i=2;i<=n;i++)
		for(re p=s1[i];p>=c1[i].w;p--)
			f[p]=max(f[p],f[p-c1[i].w]+c1[i].v);
	g[c2[1].w]=c2[1].v;
	for(re i=2;i<=m;i++)
		for(re p=s2[i];p>=c2[i].w;p--)
			g[p]=max(g[p],g[p-c2[i].w]+c2[i].v);			
	for(re i=1;i<=up;i++) ans=max(ans,f[i]+g[i]);
	printf("%lld\\n",ans);
	return 0;
}


T2 树上竞技

留坑

T3 虚构推理

思路:我在考场上看错题了,这道题其实是将时针与时针的夹角比较,分针和分针的夹角比较,然后取个\\(max\\),但是我直接把当前时间点的角度进行了比较。知道了题意,那我们考虑做法,首先我们可以枚举\\(i,j,k\\)表示时,分,秒。然后计算取最小的最大值即可。
计算的话利用一个\\(upper_bound\\)将排序后的数组二分查找即可。
注意1.我们要将边界设为\\(a_0=a_n,a_{n+1}=a_1\\),这样可以避免很多问题。
2.在计算角度的时候我们利用了\\(t2=t1+180\\),但是要计算夹角我们要用\\(180-t2-a_p\\),不能直接用\\(t1-a_p\\),因为这样算出来的夹角可能是钝角。
代码如下:

AC_code

#include<bits/stdc++.h>
#define re register int
#define ii inline int
#define iv inline void
#define f() cout<<"fuck"<<endl
#define head heeadd
#define next net
#define D double
using namespace std;
const int N=5e4+10;
const double eps=1e-6;
int n;
double ans=999999999.999999;
int h[N],m[N],s[N];
double du[N],dh[N],dm[N];
char ch[N];
ii read()
{
	int x=0;char ch=getchar();bool f=1;
	while(ch<\'0\' or ch>\'9\')
	{
		if(ch==\'-\') f=0;
		ch=getchar();
	}
	while(ch>=\'0\' and ch<=\'9\')
	{
		x=(x<<1)+(x<<3)+(ch^48);
		ch=getchar();
	}
	return f?x:(-x);
}
signed main()
{
	freopen("unreal.in","r",stdin),freopen("unreal.out","w",stdout);
	n=read();
	for(re i=1;i<=n;i++)
	{
		scanf("%s",ch+1);
		int len=strlen(ch+1),tmp=0,flag=0;
		for(re j=1;j<=len;j++)
		{
			if(ch[j]==\':\')
			{
				if(flag==0) h[i]=tmp;
				else if(flag==1) m[i]=tmp;
				++flag,tmp=0;
				continue;
			}
			tmp=tmp*10+ch[j]-\'0\';
		}
		s[i]=tmp;
		if(h[i]>=12) h[i]=h[i]%12;
		dh[i]=(double)h[i]*30.00000+(double)m[i]*0.50000+(double)s[i]*0.5/60.0;
		dm[i]=(double)m[i]*6.00000+(double)s[i]*0.10000;
	}
	sort(dh+1,dh+n+1),sort(dm+1,dm+n+1);
	dh[0]=dh[n],dh[n+1]=dh[1];
	dm[0]=dm[n],dm[n+1]=dm[1];
	for(re i=0;i<12;i++)
	{
		for(re j=0;j<60;j++)
		{
			for(double k=0.00000;k<60;k+=0.01)
			{
				double maxx=0.000,t1,t2;
				int pos;
				
				t1=(double)i*30.0000+(double)j*0.50000+k*0.5/60.0;
				t2=t1+180.00;
				if(t2>=360) t2-=360.00;
				pos=upper_bound(dh+1,dh+n+1,t2)-dh;
				double tmp1=180-(dh[pos]-t2);
				double tmp2=180-(t2-dh[pos-1]);
				if(tmp1>=360) tmp1-=360;if(tmp1<0) tmp1+=360;
				if(tmp2>=360) tmp2-=360;if(tmp2<0) tmp2+=360;
				
				t1=(double)j*6.00+k*0.10;
				t2=t1+180.00;
				if(t2>=360) t2-=360.00;
				pos=upper_bound(dm+1,dm+n+1,t2)-dm;
				double tmp3=180-(dm[pos]-t2);
				double tmp4=180-(t2-dm[pos-1]);
				if(tmp3>=360) tmp3-=360;if(tmp3<0) tmp3+=360;
				if(tmp4>=360) tmp4-=360;if(tmp4<0) tmp4+=360;
				
				tmp1=min(tmp1,360-tmp1);
				tmp2=min(tmp2,360-tmp2);
				tmp3=min(tmp3,360-tmp3);
				tmp4=min(tmp4,360-tmp4);
				maxx=max(max(tmp1,tmp2),max(tmp3,tmp4));
				ans=min(ans,maxx);
			}
		}
	}
	printf("%.6lf\\n",ans);
	return 0;
}

以上是关于noip模拟66的主要内容,如果未能解决你的问题,请参考以下文章

不等数列(noip 2014 模拟题)

noip模拟赛 不等数列

noip模拟赛 写代码

在流星应用程序上运行 ios 模拟器时出现错误“命令失败,退出代码 66”

NOIP模拟赛16

NOIp模拟赛binary