zoukankan      html  css  js  c++  java
  • uva12589

    题目大意:给n(n<=50)个向量(xi,yi) (0<=xi<=yi<=50),选出其中k(1<=k<=n)个,从(0,0)点开始,依次首尾相连,求此k个向量与x正半轴围成的最大面积的两倍并输出。

    初步想法,向量都在第一象限,所以最优解一定是选中k个排成上凸曲线。故第一步是按照向量斜率排序!

    然后就是迭代dp了。

    先看看暴力方程dp[i][j][y]=max(dp[i][j][y],dp[o][j-1][y-li[i].y]+f(li[i].x,li[i].y,y)) (对于任意的i>o>=j)这个时候需要枚举o,效率是很不乐观的。

    优化:假设dp[i][*][*]都已经求出来了。

    那么dp[i+1][j][y]=max(dp[i][j][y],dp[i][j-1][y-li[i+1].y]+f(li[i+1].x,li[i+1].y,y)),这样i推出i+1就是O(1)的效率了,初始状态就是dp[x][0][0]=0。

    再加上一点剪枝,这样就是很好的solution了。

    再看看样例,有T<=110个case,所以不能每次循环都memset(dp,0,sizeof(dp))一遍,加访问标记。(建议ACMer新手每次一定要记得看看样例有多少组)

     1 #include <iostream>
     2 #include <cstdio>
     3 #include <cstring>
     4 #include <algorithm>
     5 #include <cmath>
     6 using namespace std;
     7 int dp[51][51][2501];
     8 int stamps[51][51][2501];
     9 struct line{
    10     int x,y;
    11     friend bool operator<(line S,line T){
    12         return S.y*T.x > T.y*S.x;
    13     }
    14 }li[55];
    15 int main()
    16 {
    17     int cases; cin>>cases;
    18     int n,k;
    19     for(int cas=1;cas<=cases;cas++){
    20         scanf("%d%d",&n,&k);
    21         for(int i=1;i<=n;i++)
    22             scanf("%d%d",&li[i].x,&li[i].y);
    23         for(int i=0;i<=n;i++)
    24             dp[i][0][0]=0,stamps[i][0][0]=cas;
    25         sort(li+1,li+n+1);
    26         int t;
    27         for(int i=1;i<=n;i++){
    28             int maxj=min(i,k),minj=max(1,k-(n-i+1));
    29             for(int j=minj;j<=maxj;j++){
    30                 for(int y=2500;y>=0;y--){
    31                     dp[i][j][y]=0;
    32                     if(i>j && stamps[i-1][j][y]>=cas) dp[i][j][y]=dp[i-1][j][y], stamps[i][j][y]=cas;
    33                     if((y-li[i].y)>=0 && stamps[i-1][j-1][y-li[i].y]>=cas)
    34                         dp[i][j][y] = max(dp[i][j][y],dp[i-1][j-1][y-li[i].y]+(y+y-li[i].y)*li[i].x), stamps[i][j][y]=cas;
    35                 }
    36             }
    37         }
    38         int ans=0;
    39         for(int y=2500;y>=0;y--)
    40         if(stamps[n][k][y]>=cas) ans=max(ans,dp[n][k][y]);
    41         printf("Case %d: %d
    ",cas,ans);
    42     }
    43     return 0;
    44 }
    View Code
  • 相关阅读:
    Linux
    python中元类
    POJ 1182 食物链
    POJ 1733 Parity game
    top 介绍
    周记 2014.8.31
    windows10配置python
    oracle执行update时卡死问题的解决办法
    An Easy Introduction to CUDA C and C++
    super()
  • 原文地址:https://www.cnblogs.com/karlvin/p/3341771.html
Copyright © 2011-2022 走看看