3 条题解
-
1
看神犇们都用 DP 做,本蒟蒻还不会 DP ,就只能用学过的最短路算法来做了。(希望能早日像神犇一样学会 DP )
基本思路: 把整个图的每一个点能到达的 个点都使用链式前向星存边,边权就为终点的金币数的相反数(因为是求最长路),然后使用能够处理负权边的 SPFA 算法处理,接着找出图的最后一列的 个点的路径长度的相反数的最大值作为 ,最后输出就可以了。
注意: 需要考虑一下节点数和边数,不要把数组开小了。 还要把二维图转化为一维。
(尽管代码很长,但看了一下,用最短路算的是比 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
- 上传者