zoukankan      html  css  js  c++  java
  • codevs 4438 YJQ runs upstairs

    题目大意:求一条方差最小的路径,给定起点和中点。

    我们先考虑方差的计算公式,可以知道:方差与路径平方和,路径长度,路径段数有关。

    由于看起来数据范围较小,我们考虑dp[i=(第几个点)][j=(经过几条边)][k=(边权和)]=该限制下的路径最小平方和。

    怎么实现这个dp?
    拓扑排序套枚举j,k刚好。
    最后的答案一定在dp[n][j][k]里,枚举找最小值即可。

    #include<iostream>
    #include<cstdio>
    #include<cstring>
    #include<queue>
    #include<cmath>
    #define maxn 1000000007
    #define maxv 55
    #define maxe 305
    #define maxd 25
    using namespace std;
    struct edge
    {
    long long v,w,nxt;
    }e[maxe];
    long long n,m,g[maxv],dp[maxv][maxd][16005];
    long long x,y,z,nume=0,inq[maxv],sum=0;
    double ans=127;
    void addedge(long long uu,long long vv,long long ww)
    {
    e[++nume].v=vv;
    e[nume].w=ww;
    e[nume].nxt=g[uu];
    g[uu]=nume;
    }
    void topu()
    {
    queue <long long> q;
    for (long long i=1;i<=n;i++)
    {
    if (inq[i]==0)
    q.push(i);
    }
    dp[1][0][0]=0;
    while (!q.empty())
    {
    long long head=q.front();
    q.pop();
    for (long long j=0;j<=20;j++)
    for (long long k=0;k<=sum;k++)
    {
    if (dp[head][j][k]!=maxn)
    {
    for (long long i=g[head];i;i=e[i].nxt)
    {
    long long v=e[i].v,w=e[i].w;
    if ((j+1<=20) && (k+w<=sum))
    dp[v][j+1][k+w]=min(dp[v][j+1][k+w],dp[head][j][k]+w*w);
    }
    }
    }
    for (long long i=g[head];i;i=e[i].nxt)
    {
    if (!--inq[e[i].v])
    q.push(e[i].v);
    }
    }
    }
    int main()
    {
    freopen("library.in","r",stdin);
    freopen("library.out","w",stdout);
    memset(g,0,sizeof(g));
    memset(inq,0,sizeof(inq));
    scanf("%lld%lld",&n,&m);
    for (long long i=1;i<=m;i++)
    {
    scanf("%lld%lld%lld",&x,&y,&z);
    addedge(x,y,z);
    inq[y]++;
    sum=sum+z;
    }
    for (long long i=0;i<=n;i++)
    for (long long j=0;j<=20;j++)
    for (long long k=0;k<=sum;k++)
    dp[i][j][k]=maxn;
    topu();
    for (long long j=1;j<=20;j++)
    for (long long k=0;k<=sum;k++)
    ans=min(ans,((double)dp[n][j][k]/(double)j)-(double)(k*k)/(double)(j*j));
    printf("%.4f",ans);
    return 0;
    }

  • 相关阅读:
    116. Populating Next Right Pointers in Each Node
    117. Populating Next Right Pointers in Each Node II
    经典排序算法总结(含JAVA代码实现)
    Android面试算法篇(java)
    Android单例模式
    Android进阶-Android APK安装过程
    Android进阶-Android性能优化总结
    Android进阶-Android内存泄漏总结
    Android进阶-Android权限处理
    Android进阶-一个APP从启动到主页显示经过了哪些过程?
  • 原文地址:https://www.cnblogs.com/ziliuziliu/p/5061300.html
Copyright © 2011-2022 走看看