zoukankan      html  css  js  c++  java
  • 洛谷P3800 Power收集

    题目

    https://www.luogu.com.cn/problem/P3800

    思路

    显然这是一道DP题,朴素算法很容易想:

    [dp[i][j]=v[i][j]+max(dp[i-1][k])(j-tleq kleq j+t) ]

    然而这样的转移是(O(nm^2))的,不合要求,还要继续优化。

    注意到(kleq 4000),棋盘的数据是相当稀疏的,那么我们考虑将有P点的格子当成一个结点,建图。根据题意(必须一直向下走)该图是一个DAG。

    边的构造:将结点按x坐标从小到大排序,可以算出从i结点的行到j结点的行经过的时间(x_j-x_i),那么如果这段时间内能从i结点到j结点,那么建一条从i到j的有向边。

    跑一遍记忆化dfs就行了。

    易错点:不要以为答案就是dfs(1),因为最优解完全可以从空格子开始,起点是不固定的。

    代码

    #include<cstdlib>
    #include<algorithm>
    using namespace std;
    struct node{
        int x,y,val;
        bool operator <(node t){
            return x<t.x;
        }
    } a[4001];
    int book[4001][4001],dp[4001],k,vis[4001];
    int dfs(int x){
        int i;
        vis[x]=1;
        if(dp[x]) return dp[x];
        dp[x]=a[x].val;
        for(i=x+1;i<=k;i++){
            if(book[x][i]) dp[x]=max(dp[x],a[x].val+dfs(i));
        }
        return dp[x];
    }
    int main(){
        int i,j,l,n,m,t,x,y,z;
        int ans=0;
        scanf("%d%d%d%d",&n,&m,&k,&t);
        for(i=1;i<=k;i++)
            scanf("%d%d%d",&a[i].x,&a[i].y,&a[i].val);
        sort(a+1,a+k+1);
        for(i=1;i<=k;++i){
            for(j=i+1;j<=k;++j){
                int l=a[i].y-(a[j].x-a[i].x)*t;
                int r=a[i].y+(a[j].x-a[i].x)*t;
                if(a[j].y>=l&&a[j].y<=r) book[i][j]=1;
            }
        }
        for(i=1;i<=k;++i){
            if(!vis[i]) dfs(i);
        }
        for(i=1;i<=k;i++)
            ans=max(ans,dp[i]);
        printf("%d",ans);
        return 0;
    }
  • 相关阅读:
    SpringBoot Mybatis的驼峰命名
    设计模式之单例模式
    Java调用TSC打印机进行打印
    DOM与Jquery方法对照表(versions:Itcast)
    jQuery选择器过滤器
    算法的力量转自李开复
    源码中的相对路径和绝对路径
    C语言I博客作业03
    firstprogram
    C语言I博客作业02
  • 原文地址:https://www.cnblogs.com/landmine-sweeper/p/14102014.html
Copyright © 2011-2022 走看看