zoukankan      html  css  js  c++  java
  • Topcoder SRM 608 div1 题解

    Easy(300pts):

    题目大意:有n个盒子,一共有S个苹果,每个盒子有多少个苹果不知道,但是知道每个盒子的苹果下限和上限。现在要至少选择X个苹果,问如果要保证无论如何都能获得至少X个苹果,至少需要选择多少个盒子。数据满足n<=50。

    首先第一个方面,如果我们选择的盒子的下限大于等于X,那么显然我们一定可以获得那么多的苹果,

    所以我们将盒子的下限排序,然后从大到小累加即可。

    另一方面,如果我们没有选择的盒子的上限小于等于S-X,那么显然我们也一定可以获得那么多的苹果,

    于是我们再按照上限排序,然后扫一遍累加即可。

    时间复杂度O(nlogn),代码如下:

     1 #include <bits/stdc++.h>
     2 #define Maxn 57
     3 using namespace std;
     4 int n;
     5 int l[Maxn],r[Maxn];
     6 class MysticAndCandies
     7 {
     8     public:
     9     int minBoxes(int C, int X, vector <int> low, vector <int> high)
    10     {
    11         n=low.size();
    12         for (int i=1;i<=n;i++) l[i]=low[i-1];
    13         for (int i=1;i<=n;i++) r[i]=high[i-1];
    14         sort(l+1,l+n+1);
    15         sort(r+1,r+n+1);
    16         for (int i=1;i<n+1-i;i++) swap(l[i],l[n+1-i]),swap(r[i],r[n+1-i]);
    17         int ans,sum1=0,sum2=0;
    18         for (int i=1;i<=n;i++) sum2+=r[i];
    19         for (ans=1;ans<=n;ans++)
    20         {
    21             sum1+=l[ans];
    22             sum2-=r[ans];
    23             if (sum1>=X||C-sum2>=X) break;
    24         }
    25         return ans;
    26     }
    27 };

    Medium(600pts):

    题目大意:给出一个n个点的有向图,假设长度为L的路径一共有S条(路径可以经过重复的点多次,S也可以是无穷大),问当L非常大的时候,S的量级是L的几次方。当然,有可能S不能用L的几次方表示,那么输出-1。数据满足n<=50。

    通过题面来看,就感觉这题很厉害。。。

    我们先从一个环来考虑,一个环的长度为L的路径显然只有有数条,那么这个时候S就是L的一次方量级。

    然后我们来考虑一个强联通分量,如果这个强联通分量不仅仅只是一个环,那么路径条数就是指数级别的了。

    回到原题,我们把原图中的强联通分量全部求出来,

    至少图变成了一个DAG,然后发现所有的SCC必须是环,

    然后差不多dp之类的都可以做了。

    由于这道题n<=50,所以根本不需要什么Tarjan,直接floyed就行了。

    时间复杂度O(n^3),代码如下:

     1 #include <bits/stdc++.h>
     2 #define Maxn 57
     3 using namespace std;
     4 bool vis[Maxn][Maxn];
     5 int fa[Maxn],sum[Maxn],sumedge[Maxn];
     6 int r[Maxn],f[Maxn];
     7 int n;
     8 class BigO
     9 {
    10     public:
    11     int minK(vector <string> graph)
    12     {
    13         n=graph.size();
    14         for (int i=0;i<n;i++)
    15             for (int j=0;j<n;j++)
    16                 if (graph[i][j]=='Y') vis[i][j]=true; else vis[i][j]=false;
    17         for (int i=0;i<n;i++)
    18             vis[i][i]=true;
    19         for (int k=0;k<n;k++)
    20             for (int i=0;i<n;i++)
    21                 for (int j=0;j<n;j++)
    22                     if (vis[i][k]&&vis[k][j]) vis[i][j]=true;
    23         memset(sum,0,sizeof(sum));
    24         for (int i=0;i<n;i++)
    25             for (int j=0;j<n;j++)
    26                 if (vis[i][j]&&vis[j][i])
    27                 {
    28                     fa[i]=j;
    29                     ++sum[j];
    30                     break;
    31                 }
    32         memset(sumedge,0,sizeof(sumedge));
    33         for (int i=0;i<n;i++)
    34             for (int j=0;j<n;j++)
    35                 if (graph[i][j]=='Y'&&fa[i]==fa[j]&&i!=j)
    36                     ++sumedge[fa[i]];
    37         memset(r,0,sizeof(r));
    38         memset(f,0,sizeof(f));
    39         for (int i=0;i<n;i++)
    40         {
    41 //the SCC is more than a circle
    42             if (sumedge[i]>sum[i]) return -1;
    43 //the SCC is more than a point
    44             if (sumedge[i]!=0) r[i]=1;
    45             f[i]=r[i];
    46         }
    47         for (int T=0;T<n;T++)
    48             for (int i=0;i<n;i++)
    49                 for (int j=0;j<n;j++)
    50                     if (fa[i]!=fa[j]&&graph[i][j]=='Y')
    51                         f[fa[j]]=max(f[fa[j]],f[fa[i]]+r[fa[j]]);
    52         int res=0;
    53         for (int i=0;i<n;i++)
    54             res=max(f[i]-1,res);
    55         return res;
    56     }
    57 };

    Hard(900pts):

    题目大意:有一个机器人在x轴上,初始位置为0,它接受到了一系列指令,每次向左一个单位或者向右一个单位。如果现在在左边界上,那么就不能再往左了,向左的指令会被忽略;如果现在在右边界上,那么就不能再往右了,向右的指令会被忽略。现在对于minA<=A<=maxA,minB<=B<=maxB,求出以A为左边界,B为右边界的最终位置的总和,数据满足所有数<=5000。

    这题是个神结论题,不打算多说。。。

    我们假设边界都是无穷大的时候,求出出现过的最左侧位置和最右侧位置。

    如果A和B分别大于等于两边边界,那么答案就是最终位置。

    如果不是的话,有一个结论就是(a,b)等于(a-1,b+1)-1,然后按照差暴力就可以了。

    时间复杂度O(nX+X^2),代码如下:

     1 #include <bits/stdc++.h>
     2 #define Maxa 5007
     3 using namespace std;
     4 int ans[Maxa][Maxa];
     5 string s;
     6 long long res=0;
     7 class OneDimensionalRobot
     8 {
     9     public:
    10     long long theSum(vector <string> commands1, vector <string> commands2, int minA, int maxA, int minB, int maxB)
    11     {
    12         s.clear();
    13         for (int i=0;i<commands1.size();i++) s+=commands1[i];
    14         for (int i=0;i<commands2.size();i++) s+=commands2[i];
    15         int left=0,right=0,pos=0;
    16         for (int i=0;i<s.length();i++)
    17         {
    18             if (s[i]=='R') ++pos; else --pos;
    19             if (-pos>left) left=-pos;
    20             if (pos>right) right=pos;
    21         }
    22         memset(ans,0,sizeof(ans));
    23         for (int i=minA;i<=maxA;i++)
    24             for (int j=minB;j<=maxB;j++)
    25             {
    26                 if (i>=left&&j>=right) ans[i][j]=pos; else
    27                 if (i==minA||j==maxB)
    28                 {
    29                     int now=0;
    30                     for (int k=0;k<s.length();k++)
    31                     {
    32                         if (s[k]=='R') ++now; else --now;
    33                         if (-now>i) now=-i;
    34                         if (now>j) now=j;
    35                     }
    36                     ans[i][j]=now;
    37                 } else
    38                 {
    39                     ans[i][j]=ans[i-1][j+1];
    40                     if (left>i-1||right>j) --ans[i][j];
    41                 }
    42             }
    43         for (int i=minA;i<=maxA;i++)
    44             for (int j=minB;j<=maxB;j++)
    45                 res+=ans[i][j];
    46         return res;
    47     }
    48 };
  • 相关阅读:
    JavaScript获取查询字符串
    Struts2 验证码图片实例
    js函数重载
    js面向对象基础
    js上下文
    java克隆入门和深入
    js类型检查
    js闭包
    Phonegap移动开发:布局总结(一) 全局
    Python发送多附件邮件的方法
  • 原文地址:https://www.cnblogs.com/Tommyr7/p/6970679.html
Copyright © 2011-2022 走看看