zoukankan      html  css  js  c++  java
  • HDU 4341 Gold miner (分组背包)

    先把线按照距离原点的距离排序,然后用叉积把在同一条直线上的点放在一起,

    把在同一条线上的点中的前i个点当成一个点就转化成了分组背包。

    写if(kas++) putchar(' ') 居然PE了,PE选手

    #include<bits/stdc++.h>
    using namespace std;
    int N,T;
    const int maxn = 203;
    const int MAXT = 40005;
    struct Point
    {
        int x,y,t,v;
    
    }P[maxn];
    
    bool vis[maxn];
    vector<int> Line[maxn];
    int Line_cnt;
    #define PB push_back
    
    int Dot(const Point &a,const Point& b) { return a.x*b.x+a.y*b.y; }
    double Length(const Point &x) { return sqrt(Dot(x,x)); }
    int Cross(Point &a,Point &b)
    {
        return a.x*b.y-b.x*a.y;
    }
    bool operator < (const Point& a,const Point & b) { return Length(a)<Length(b); }
    
    
    void init()
    {
        memset(vis,0,sizeof(vis));
        for(int i = 0; i < N; i++){
            scanf("%d%d%d%d",&P[i].x,&P[i].y,&P[i].t,&P[i].v);
        }
        sort(P,P+N);
        Line_cnt = 0;
        for(int i = 0; i < N; i++)if(!vis[i]){
            Line[Line_cnt].clear();
            for(int j = i; j < N; j++)if(!vis[j]){
                if(Cross(P[i],P[j]) == 0){
                    vis[j] = true;
                    Line[Line_cnt].PB(j);
                }
            }
            Line_cnt++;
        }
    }
    
    int f[2][MAXT];
    
    void dp()
    {
        fill(f[0],f[0]+1+T,0);
        fill(f[1],f[1]+1+T,0);
        for(int i = 0; i < Line_cnt; i++){
            int pre = i&1,cur = pre^1;
            int totV = 0, totT = 0;
            for(int j = 0; j < Line[i].size(); j++){
                Point& x = P[Line[i][j]];
                totV += x.v; totT += x.t;
                for(int k = T; k >= totT; k--){
                    f[cur][k] = max(f[cur][k],f[pre][k-totT]+totV);
                }
            }
            for(int k = 0; k <= T; k++){
                f[cur][k] = max(f[cur][k],f[pre][k]);
            }
        }
    }
    
    int main()
    {
        int kas = 0;
        while(~scanf("%d%d",&N,&T)){
            init();
            dp();
            printf("Case %d: %d
    ",++kas,max(f[0][T],f[1][T]));
        }
        return 0;
    }

    当时并不知道如何用一维数组实现,补上一维的伪代码

    for 所有的组k

        for v=V..0 //从大到小枚举V

            for 所有的i属于组k 

                f[v]=max{f[v],f[v-c[i]]+w[i]}//从小的V转移,是上一组的状态

  • 相关阅读:
    Go源码文件与命令
    K8s控制器
    odoo 在form视图sheet右上角增加按钮
    odoo 常用widget
    odoo tree视图中实现横向滚动条
    可能是智障的高二生活
    千题计划
    闲谈
    线性代数与simplex
    好题集锦
  • 原文地址:https://www.cnblogs.com/jerryRey/p/4746025.html
Copyright © 2011-2022 走看看