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
  • 相关阅读:
    WCF Server Console
    Restart IIS With Powershell
    RestartService (recursively)
    Copy Files
    Stopping and Starting Dependent Services
    多线程同步控制 ManualResetEvent AutoResetEvent MSDN
    DTD 简介
    Using Powershell to Copy Files to Remote Computers
    Starting and Stopping Services (IIS 6.0)
    java中的NAN和INFINITY
  • 原文地址:https://www.cnblogs.com/karlvin/p/3341771.html
Copyright © 2011-2022 走看看