3 条题解

  • 1
    @ 2025-1-5 21:17:11

    看神犇们都用 DP 做,本蒟蒻还不会 DP ,就只能用学过的最短路算法来做了。(希望能早日像神犇一样学会 DP )

    基本思路: 把整个图的每一个点能到达的 33 个点都使用链式前向星存边,边权就为终点的金币数的相反数(因为是求最长路),然后使用能够处理负权边的 SPFA 算法处理,接着找出图的最后一列的 55 个点的路径长度的相反数的最大值作为 ansans ,最后输出就可以了。
    注意: 需要考虑一下节点数和边数,不要把数组开小了。 还要把二维图转化为一维。
    (尽管代码很长,但看了一下,用最短路算的是比 DP 快的。)
    下面附上 AC 代码:

    #include<bits/stdc++.h>
    using namespace std;
    struct edge
    {
    	int to,next,w;
    }a[150001];
    int i,j,n,u,v,w,cnt,ans,m[5][10000],head[50001],dis[50001];
    bool vis[50001];
    queue<int>q;
    bool check(int x,int y)
    {
    	if (x<0||y<0||x>4||y>=n)
    		return false;
    	return true;
    }
    void add(int u,int v,int w)
    {
    	a[++cnt].to=v;
    	a[cnt].next=head[u];
    	head[u]=cnt;
    	a[cnt].w=-w;
    	return;
    }
    int ex(int x,int y)
    {
    	return x*n+y;
    }
    void spfa(int s)
    {
    	for (int i=1;i<2001;++i)
    		dis[i]=0x3fffffff;
    	dis[s]=0;
    	vis[s]=true;
    	q.push(s);
    	while (!q.empty())
    	{
    		int u=q.front();
    		vis[u]=false;
    		q.pop();
    		for (int i=head[u];i!=0;i=a[i].next)
    			if (dis[a[i].to]>dis[u]+a[i].w)
    			{
    				dis[a[i].to]=dis[u]+a[i].w;
    				if (!vis[a[i].to])
    				{
    					vis[a[i].to]=true;
    					q.push(a[i].to);
    				}
    			}
    	}
    	return;
    }
    int main()
    {
    	scanf("%d",&n);
    	for (i=0;i<5;++i)
    		for (j=0;j<n;++j)
    			scanf("%d",&m[i][j]);
    	for (i=0;i<5;++i)
    		for (j=0;j<n;++j)
    		{
    			if (check(i-1,j+1))
    				add(ex(i,j),ex(i-1,j+1),m[i-1][j+1]);
    			if (check(i,j+1))
    				add(ex(i,j),ex(i,j+1),m[i][j+1]);
    			if (check(i+1,j+1))
    				add(ex(i,j),ex(i+1,j+1),m[i+1][j+1]);
    		}
    	spfa(ex(2,0));
    	for (i=0;i<5;++i)
    		ans=max(ans,-dis[ex(i,n-1)]);
    	printf("%d",ans);
    	return 0;
    }
    

    希望明年科技节信息竞赛我能拿特等奖。

    信息

    ID
    950
    时间
    1000ms
    内存
    256MiB
    难度
    6
    标签
    递交数
    90
    已通过
    16
    上传者