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;
    }
    

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

    • 1
      @ 2024-11-23 13:17:41
      #include<bits/stdc++.h>
      #define int long long
      using namespace std;
      const int N=1e4+5;
      int n,k,ans;
      int a[10][N];
      int f[10][N];
      signed main(){
      	cin>>n;
      	for(int i=1;i<=5;i++){
      		for(int j=1;j<=n;j++){
      			cin>>a[i][j];
      		} 
      	}
      	f[3][1]=a[3][1]; 
      	a[1][1]=a[2][1]=a[4][1]=a[5][1]=a[1][2]=a[5][2]=0;	
      	
      	for(int i=1;i<=5;i++) f[i][1]=0;
      	
      	for(int i=2;i<=n;i++){
      		f[1][i]=max(f[1][i-1],f[2][i-1])+a[1][i];
      		f[5][i]=max(f[5][i-1],f[4][i-1])+a[5][i];
      		for(int j=2;j<=4;j++){
      			f[j][i]=max(max(f[j][i-1],f[j-1][i-1]),f[j+1][i-1])+a[j][i];
      		}
      	}
      	ans=0;
      	for(int i=1;i<=5;i++) ans=max(ans,f[i][n]);
      	cout<<ans;
      	return 0;
      }
      

      数组开爆了我哭死QAQ

      • 0
        @ 2024-11-23 8:25:10
        #include <bits/stdc++.h>
        #define int long long
        using namespace std;
        const int N = 1e4+5;
        int a[10][N],dp[10][N];
        int n;
        signed main()
        {
        	cin>>n;
        	for(int i=1;i<=5;i++)
        		for(int j=1;j<=n;j++)
        			cin>>a[i][j],dp[i][j]=a[i][j];
        	dp[1][2]=0;
        	dp[5][2]=0;
        	for(int i=3;i<=n;i++)
        	{
        		for(int j=1;j<=5;j++)
        		{
        			dp[j][i]=dp[j][i]+max(max(dp[j][i-1],dp[j-1][i-1]),dp[j+1][i-1]);
        		}
        	}
        	int ans=0;
        //	for(int i=1;i<=5;i++)
        //	{
        //		for(int j=1;j<=n;j++)
        //		{
        //			cout<<dp[i][j]<<' ';
        //		}
        //		cout<<'\n';
        //	}
        	for(int i=1;i<=5;i++)
        		ans=max(ans,dp[i][n]);
        	cout<<ans;
        	return 0;
        }
        
        • 1

        信息

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