• EZ 2018 04 21 NOIP2018 模拟赛(九)


    终于停止了掉Rating的浪潮!

    猥琐的链接

    这次200分才Rank10,而且很多人并列

    庆幸T2最后20分钟发现期望的算法打错了,然后拿到了50pts,250收场

    T1 水题*1

    这道题不仅做过,而且本来难度就很低,不A对不起自己

    主要是一个追及问题,我们枚举所有的人初始时的位置即可

    CODE

    #include<cstdio>
    using namespace std;
    const int N=1005;
    int n;
    double v,u,d[N],c[N],ans;
    int main()
    {
    	//freopen("A.in","r",stdin); freopen("A.out","w",stdout);
    	register int i,j;
    	scanf("%d%lf%lf",&n,&v,&u);
    	for (i=1;i<=n;++i)
    	scanf("%lf",&c[i]);
    	for (i=1;i<=n;++i)
    	scanf("%lf",&d[i]);
    	for (i=1;i<=n;++i)
    	for (j=1;j<=n;++j)
    	ans+=u/(c[i]-(j-1)*d[i]-v);
    	printf("%.3lf",ans);
    	return 0;
    }
    

    T2 水题*2

    话说再给我半小时小时应该可以A了这题(A的人比T3多了去了)

    写完DFS后其实就有两条路:记忆化||概率DP

    记忆化比较舒服,但我还是太蒟(主要是正着来比较难写)

    而且这题的DP转移也比较好写,因此我们考虑倒着DP

    设f[i][j]表示还剩下j(minites)时在i点时的期望

    因此转移的时候只要与它相连的所有可行的点转移即可,最后再对起点分类讨论

    CODE

    #include<cstdio>
    #include<cstring>
    using namespace std;
    typedef double DB;
    const int N=105,T=500;
    struct edge
    {
    	int to,next,v;
    }e[N*N<<1];
    DB f1[N][T],f2[N][T];
    int n,m,t,head[N],h1[N],h2[N],c[N],cnt,x,y,z;
    inline char tc(void)
    {
    	static char fl[100000],*A=fl,*B=fl;
    	return A==B&&(B=(A=fl)+fread(fl,1,100000,stdin),A==B)?EOF:*A++;
    }
    inline void read(int &x)
    {
    	x=0; char ch=tc();
    	while (ch<'0'||ch>'9') ch=tc();
    	while (ch>='0'&&ch<='9') x=x*10+ch-'0',ch=tc();
    }
    inline void add(int x,int y,int z)
    {
    	e[++cnt].to=y; e[cnt].v=z; e[cnt].next=head[x]; head[x]=cnt;
    }
    int main()
    {
    	//freopen("B.in","r",stdin); freopen("B.out","w",stdout);
    	memset(e,-1,sizeof(e));
    	memset(head,-1,sizeof(head));
    	register int i,j,k;
    	read(n); read(m); read(t);
    	for (i=1;i<=n;++i)
    	read(c[i]),read(h1[i]),read(h2[i]);
    	for (i=1;i<=m;++i)
    	{
    		read(x); read(y); read(z);
    		add(x,y,z); add(y,x,z);
    	}
    	for (j=t;j>=1;--j)
    	for (i=1;i<=n;++i)
    	{
    		int res=0;
    		for (k=head[i];k!=-1;k=e[k].next)
    		if (j+e[k].v+c[e[k].to]<=t) ++res;
    		f1[i][j]=h1[i]; f2[i][j]=h2[i];
    		if (!res) continue;
    		for (k=head[i];k!=-1;k=e[k].next)
    		if (j+e[k].v+c[e[k].to]<=t)
    		{
    			f1[i][j]+=f1[e[k].to][j+e[k].v+c[e[k].to]]/res;
    			f2[i][j]+=f2[e[k].to][j+e[k].v+c[e[k].to]]/res;
    		}
    	}
    	DB ans1=0,ans2=0;
    	int res=0;
    	for (i=1;i<=n;++i)
    	if (c[i]<=t) ++res;
    	for (i=1;i<=n;++i)
    	if (c[i]<=t) ans1+=f1[i][c[i]]/res,ans2+=f2[i][c[i]]/res;
    	printf("%.5lf %.5lf",ans1,ans2);
    	return 0;
    }
    

    T3 水题*3

    状压DP即可(怎么这么多dalao直接DFS艹过去了)

    这题我们需要3个状态对于所有任务:0表示还未取,1表示取来了但是还没有送到,2表示已经送到了,因此f[i][j]表示在i点时状态为j(三进制数)最短时间

    注意如果只设01那么你难以区分没取和取了没送到的;或是取了没送到的和取了送到的

    而且可以一次接多个任务,因此可能会有中转点的干扰

    所以每次转移时枚举每一个点再搞一下即可

    注意1只能由0转移过来,2只能由1转移过来,千万不能直接从0转移到2

    3的幂次可以预处理,因此复杂度O(3^k*k*n)

    CODE

    #include<cstdio>
    #include<algorithm>
    using namespace std;
    const int N=25,Q=15,INF=1e9;
    struct data
    {
    	int s,t,l,r;
    }a[Q];
    int dis[N][N],pow[Q],f[N][60000],n,m,q,ans=-1,x,y,z;
    inline char tc(void)
    {
    	static char fl[100000],*A=fl,*B=fl;
    	return A==B&&(B=(A=fl)+fread(fl,1,100000,stdin),A==B)?EOF:*A++;
    }
    inline void read(int &x)
    {
    	x=0; char ch=tc();
    	while (ch<'0'||ch>'9') ch=tc();
    	while (ch>='0'&&ch<='9') x=x*10+ch-'0',ch=tc();
    }
    inline int max(int a,int b)
    {
    	return a>b?a:b;
    }
    inline int min(int a,int b)
    {
    	return a<b?a:b;
    }
    inline void init(void)
    {
    	register int i,j;
    	for (pow[0]=1,i=1;i<=q;++i)
    	pow[i]=pow[i-1]*3;
    	for (i=1;i<=n;++i)
    	for (j=0;j<pow[q];++j)
    	f[i][j]=INF; f[1][0]=0;
    	for (i=1;i<=n;++i)
    	for (j=1;j<=n;++j)
    	dis[i][j]=INF;
    	for (i=1;i<=j;++i)
    	dis[i][i]=0;
    }
    inline void floyd(void)
    {
    	register int i,j,k;
    	for (k=1;k<=n;++k)
    	for (i=1;i<=n;++i)
    	for (j=1;j<=n;++j)
    	dis[i][j]=min(dis[i][j],dis[i][k]+dis[k][j]);
    }
    inline int get_num(int x,int id)
    {
    	return x/pow[id]%3;
    }
    inline int count(int x)
    {
    	int res=0;
    	while (x)
    	{
    		if (x%3==2) ++res;
    		x/=3;
    	}
    	return res;
    }
    int main()
    {
    	//freopen("C.in","r",stdin); freopen("C.out","w",stdout);
    	register int i,j,k;
    	read(n); read(m); read(q);
    	init();
    	for (i=1;i<=m;++i)
    	{
    		read(x); read(y); read(z);
    		dis[x][y]=min(dis[x][y],z);
    	}
    	floyd();
    	for (i=0;i<q;++i)
    	read(a[i].s),read(a[i].t),read(a[i].l),read(a[i].r);
    	for (j=0;j<pow[q];++j)
    	for (k=0;k<q;++k)
    	{
    		int id=get_num(j,k);
    		if (id==0) continue;
    		if (id==1)
    		{
    			for (i=1;i<=n;++i)
    			if (f[i][j-pow[k]]+dis[i][a[k].s]<=a[k].r) f[a[k].s][j]=max(a[k].l,min(f[i][j-pow[k]]+dis[i][a[k].s],f[a[k].s][j]));
    		} else
    		{
    			for (i=1;i<=n;++i)
    			if (f[i][j-pow[k]]+dis[i][a[k].t]<=a[k].r) f[a[k].t][j]=min(f[i][j-pow[k]]+dis[i][a[k].t],f[a[k].t][j]);
    		}
    	}
    	for (i=1;i<=n;++i)
    	for (j=0;j<pow[q];++j)
    	if (f[i][j]!=INF) ans=max(ans,count(j));
    	printf("%d",ans);
    	return 0;
    }
    
  • 相关阅读:
    [LeetCode]Reverse Linked List II
    [LeetCode]Remove Duplicates from Sorted List II
    嵌入式培训学习历程第六天
    嵌入式培训学习历程第五天
    嵌入式培训学习历程第三天
    嵌入式培训学习历程第二天
    嵌入式培训学习历程第一天
    shell编程
    找整除--全国模拟(二)
    最长公共连续子串--全国模拟(二)
  • 原文地址:https://www.cnblogs.com/cjjsb/p/8900985.html
Copyright © 2020-2023  润新知