• NIKKEI Programming Contest 2019-2 D 部分分题解


    请注意本文章所描写的算法只可以获得前 14 个测试点(含三个样例)的部分分,但是没有出现 WA 的情况。

    推荐阅读

    题面

    给出 (m) 个线段,每次可以从线段上任意一点以代价 (c_i) 走到线段上另一点,每条线段只能使用一次,求从 (1) 位置走到 (n) 位置的最小代价。

    部分分题解

    观察样例可以发现,在线段上走的目的其实是走到下一个线段/终点上,因此当前点转化成了当前线段的移动,一定程度上减小了时间复杂度,但是由于线段移动可行性的判断是 (O(m^2)) 的,而移动方案数也可以被卡到 (O(m^2))(起点 (s_i=s_{i-1}),终点 (t_i=t_{i-1}+1)),因此这个算法效率也并不是太高,但是此处的转化思想还是挺有意义的。

    代码

    #include<cstdio>
    #include<cstring>
    #include<queue>
    #include<algorithm>
    #include<climits>
    const int MAXN=1e5+5;
    struct Edge{int u,v,next;long long w;};
    struct Point
    {
    	int v;long long w;
    	bool operator < (const Point &b) const
    	{
    		return w==b.w?v<b.v:w>b.w;
    	}
    };
    std::priority_queue<Point>que;
    long long sample;int n,m,head[MAXN],cnt,u[MAXN],v[MAXN];bool vis[MAXN];long long dis[MAXN],w[MAXN];Edge edge[MAXN*3];
    void AddEdge(int u,int v,long long w)
    {
    	//printf("%d %d %lld
    ",u,v,w);
    	edge[++cnt].u=u;edge[cnt].v=v;edge[cnt].w=w;
    	edge[cnt].next=head[u];head[u]=cnt;
    }
    void Dijkstra()
    {
    	Point tmp,temp;
    	memset(dis,0x3f3f3f,sizeof(dis));
    	temp.v=0;temp.w=0;sample=dis[0];dis[0]=0;
    	que.push(temp);
    	while(!que.empty())
    	{
    		temp=que.top();que.pop();
    		if(vis[temp.v]) continue;
    		//printf("%d
    ",temp.v);
    		vis[temp.v]=1;
    		for(int i=head[temp.v];i;i=edge[i].next)
    		{
    			//printf("%d*
    ",edge[i].v);
    			if(dis[edge[i].v]>dis[temp.v]+edge[i].w)
    			{
    				//printf("%d ADD
    ",edge[i].v);
    				dis[edge[i].v]=dis[temp.v]+edge[i].w;
    				tmp.v=edge[i].v;
    				tmp.w=dis[edge[i].v];
    				que.push(tmp);
    			}
    		}
    	}
    }
    bool cover(int s1,int t1,int s2,int t2)
    {
    	if(t2<=t1) return 0;
    	return (s2>=s1&&t2<=t1)||(((s2<=s1&&t2>=s1)||(s2<=t1&&t2>=t1)));
    }
    int main()
    {
    	scanf("%d %d",&n,&m);
     
    	for(int i=1;i<=m;i++)
    	{
    		scanf("%d %d %lld",&u[i],&v[i],&w[i]);
    		if(u[i]==1) AddEdge(0,i,w[i]);
    	}
    	for(int i=1;i<=m;i++)
    		for(int j=1;j<=m;j++)
    			if(i!=j&&cover(u[i],v[i],u[j],v[j])) AddEdge(i,j,w[j]);
    	Dijkstra();
    	long long ans=LLONG_MAX;bool flag=0;
    	for(int j=1;j<=m;j++)
    		if(v[j]==n){ans=std::min(ans,dis[j]);}
    	printf("%lld",(ans==LLONG_MAX||ans==sample)?-1:ans);
    	return 0;
    }
    
    无特别声明的情况下,本文为原创文章,允许转载,采用知识共享署名-非商业性使用-相同方式共享 4.0 国际许可协议进行许可。
    在声明禁止转载的情况下,请勿转载;若本文章为转载的文章,版权归原作者所有。
    如果您觉得本文写得好,请点击下方的推荐按钮~若您有任何建议和指正,请在下方留言,对于您的指正将不胜感激。
  • 相关阅读:
    Python之pytest 基础
    unittest和pytest的区别
    Selenium 常用定位对象元素的方法
    ORCAl存储过程
    Mysql的存储过程
    TestNG 搭建测试框架 自动化测试
    通过junit/TestNG+java 实现自动化测试
    查看APP用到的图片方法
    码农干私活的建议(转)
    Android的onCreateOptionsMenu()创建菜单Menu详解(转)
  • 原文地址:https://www.cnblogs.com/ksyx/p/atcoder-NIKKEI-2019-2-D.html
Copyright © 2020-2023  润新知