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

    CTSC考完跑了过来日常TC~~~

    Easy(250pts):

    题目大意:有个机器人,一开始的位置在(0,0),第k个回合可以向四个方向移动3^k的距离(不能不动),问是否可以到达(x,y),数据满足|x|,|y|<=10^9。

    这题还是很简单的嘛,口亨~~~

    首先我们只考虑一个方向,于是发现,每一次可以移动3^k的距离或者不动,于是我们发现这样的序列是有且仅有一个的,

    于是我们分开考虑x和y,把两个序列全部预处理出来,

    然后直接扫一遍就做完了,

    时间复杂度O(log|x|)左右吧,代码如下:

     1 #include <bits/stdc++.h>
     2 using namespace std;
     3 class PowerOfThree
     4 {
     5     public:
     6     string ableToGet(int x, int y)
     7     {
     8         x=abs(x),y=abs(y);
     9         bool check=true;
    10         while (x!=0||y!=0)
    11         {
    12             if ((x%3==0)+(y%3==0)!=1) check=false;
    13             if (x%3==2) x=(x+1)/3; else x=x/3;
    14             if (y%3==2) y=(y+1)/3; else y=y/3;
    15         }
    16         if (check) return "Possible"; else return "Impossible";
    17     }
    18 };

    Medium(550pts):

    题目大意:有一棵n个节点的树,有若干节点上有一只狐狸,其它节点没有,所有边的距离为1。现在狐狸要聚集在一起,使得它们形成了一棵树,且每个节点依然最多只有一只狐狸,且移动距离之和最小,输出这个最小值。数据满足n<=50。

    我做过的最难的medium吧。。。这题做了我好久好久。。。

    首先,最后形成的狐狸一定是一棵树,我们枚举每一个节点i,设i是最后这棵树的root,

    我们考虑树形dp,

    设f[i][j]表示i这个节点形成的子树中一共放置了j个狐狸,且i这个节点一定有狐狸,且这j个狐狸联通的最优值。

    我们考虑如何转移,

    假设cur[j]就是当前u这个节点已经处理了若干个儿子的f[u]数组,

    于是我们能够得到f[u][i+j]就是从已经处理的若干个儿子中提取i个,从当前正在处理的v节点中提取j个的最优值,

    那么已经处理完的若干个儿子对答案的贡献度是cur[i],当前处理的v节点对答案的贡献度是f[v][j]+(u和v这条边对答案的贡献度),

    所以f[u][i+j]=cur[i]+f[v][j]+(u和v这条边对答案的贡献度),

    所以我们只需要考虑这条边的贡献度就可以了,我们假设size[u]表示u这个节点为根的子树下原始状态下有多少个狐狸,

    如果size[v]=j,那么这条边的贡献度就是0;

    如果size[v]>j,那么一定有size[v]-j个狐狸从v这个子树出来,那么一定经过这条边,所以这条边贡献度就是size[v]-j;

    如果size[v]<j,那么一定有j-size[v]个狐狸进入v这个子树中,它们也一定经过这条边,所以这条边的贡献度就是j-size[v]。

    所以无论如何,这条边的贡献度一定是abs(size[v]-j)。

    所以我们有f[u][i+j]=cur[i]+f[v][j]+abs(size[v]-j)。

    然后边界细节注意一下就可以了,时间复杂度O(n^4),代码如下:

     1 #include <bits/stdc++.h>
     2 #define Maxn 1007
     3 #define inf 1000000007
     4 using namespace std;
     5 int n,cnt,ans=inf,m;
     6 int last[Maxn],other[Maxn],pre[Maxn],sum[Maxn],size[Maxn];
     7 int f[2*Maxn][2*Maxn];
     8 int temp[4*Maxn];
     9 bool fox[Maxn];
    10 class FoxConnection
    11 {
    12     void insert(int u, int v)
    13     {
    14         other[++cnt]=v,pre[cnt]=last[u],last[u]=cnt;
    15     }
    16     void dfs(int u, int fa)
    17     {
    18         size[u]=fox[u];
    19         int cur[4*Maxn];
    20         memset(cur,0,sizeof(cur));
    21         for (int q=last[u];q;q=pre[q])
    22         {
    23             int v=other[q];
    24             if (v!=fa)
    25             {
    26                 dfs(v,u);
    27                 for (int i=0;i<=m;i++) temp[i]=inf;
    28                 for (int i=0;i<=m;i++)
    29                     for (int j=0;j<=m-i;j++)
    30                         temp[i+j]=min(temp[i+j],cur[i]+f[v][j]+abs(size[v]-j));
    31                 for (int i=0;i<=m;i++) cur[i]=temp[i];
    32                 size[u]+=size[v];
    33             }
    34         }
    35         f[u][0]=cur[0];
    36         for (int i=1;i<=m;i++) f[u][i]=cur[i-1];
    37     }
    38     int solve(int rt)
    39     {
    40         for (int i=1;i<=n;i++)
    41             for (int j=0;j<=2*n;j++)
    42                 f[i][j]=inf;
    43         dfs(rt,-1);
    44         return f[rt][m];
    45     }
    46     public:
    47     int minimalDistance(vector <int> A, vector <int> B, string haveFox)
    48     {
    49         n=A.size()+1;
    50         for (int i=0;i<n;i++) fox[i+1]=(haveFox[i]=='Y');
    51         m=0;
    52         for (int i=1;i<=n;i++) if (fox[i]) ++m;
    53         for (int i=0;i<n-1;i++)
    54             insert(A[i],B[i]),insert(B[i],A[i]);
    55         for (int i=1;i<=n;i++)
    56             ans=min(ans,solve(i));
    57         return ans;
    58     }
    59 };

    Hard(1000pts):

    这个计算几何题怎么比medium思路简单多了呢。。。

    题目大意:给了你n条线段,它们可能有交点,可能有重合,现在把它们视为一个模块,有一张10^9*10^9的长方形纸片,现在复制若干遍这个模块,要求任意两个模块不能相交,要求判断是否可以复制无穷多份。数据满足n<=50。

    这题的思路还是很简单的吧,如果能够复制无数份,那么一定是能够往某个方向移动了很小很小的距离,

    我们先把所有直线两两处理,

    如果重合,直接不用管;

    如果没有交点,直接不用管;

    如果有一个交点,而且交点不是直线的端点,直接有穷个返回答案;

    如果有一个交点,而且交点是直线的端点,那么那个方向一定有角度限制,预处理出角度限制。

    所有直线两两处理完了之后,把所有角度限制从小到大扫一遍,然后判定一下就做完了。

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

     1 #include <bits/stdc++.h>
     2 #define eps 1e-9
     3 #define Maxn 107
     4 using namespace std;
     5 int n,cnt=0;
     6 struct point {double x,y;};
     7 struct line {point a,b;};
     8 line a[Maxn];
     9 pair<double,double> cover[Maxn*Maxn*2];
    10 class FamilyCrest
    11 {
    12     double cross(double x1 ,double y1, double x2, double y2)
    13     {
    14         return (x1*y2-x2*y1);
    15     }
    16     bool samepoint(point a, point b)
    17     {
    18 //check if point a and point b are the same point
    19         if (fabs(a.x-b.x)<eps&&fabs(a.y-b.y)<eps) return true;
    20         return false;
    21     }
    22     bool sameline(line a, line b)
    23     {
    24 //check if line a and line b are the same line
    25         double res=cross(a.a.x-a.b.x,a.a.y-a.b.y,b.a.x-b.b.x,b.a.y-b.b.y);
    26         if (fabs(res)<eps) return true;
    27         return false;
    28     }
    29     double sameposition(line a, line b)
    30     {
    31 //check if the whole segment b is on the same direction of line a
    32 //answer>0 means segment b is on the same direction of line a
    33 //answer<0 means segment b has a same point with line a
    34 //answer=0 means segment b has an end point on the line a
    35         double res,res1,res2;
    36         res1=cross(a.b.x-a.a.x,a.b.y-a.a.y,b.a.x-a.a.x,b.a.y-a.a.y);
    37         res2=cross(a.b.x-a.a.x,a.b.y-a.a.y,b.b.x-a.a.x,b.b.y-a.a.y);
    38         res=res1*res2;
    39         return res;
    40     }
    41     void updata(double l, double r)
    42     {
    43         if (l<r)
    44         {
    45             cover[++cnt].first=l,cover[cnt].second=r;
    46         } else
    47         {
    48             cover[++cnt].first=l,cover[cnt].second=M_PI;
    49             cover[++cnt].first=-M_PI,cover[cnt].second=r;
    50         }
    51     }
    52     bool calc(line a, line b)
    53     {
    54 //segment a and segment b are on the same line
    55         if (sameline(a,b)) return true;
    56 //segment a and segment b don't have a same point
    57         if (sameposition(a,b)>eps) return true;
    58         if (sameposition(b,a)>eps) return true;
    59 //segment a and segment b have a same point which is not an end point
    60         if (sameposition(a,b)<-eps) return false;
    61         if (sameposition(b,a)<-eps) return false;
    62 //segment a and segment b have a same point which is an end point
    63         point O,A,B;
    64 //point O is the end point
    65         if (samepoint(a.a,b.a)) O=a.a,A=a.b,B=b.b; else
    66         if (samepoint(a.a,b.b)) O=a.a,A=a.b,B=b.a; else
    67         if (samepoint(a.b,b.a)) O=a.b,A=a.a,B=b.b; else
    68         if (samepoint(a.b,b.b)) O=a.b,A=a.a,B=b.a;
    69         if (cross(A.x-O.x,B.x-O.x,A.y-O.y,B.y-O.y)>eps) swap(A,B);
    70         updata(atan2(A.y-O.y,A.x-O.x),atan2(O.y-B.y,O.x-B.x));
    71         updata(atan2(O.y-A.y,O.x-A.x),atan2(B.y-O.y,B.x-O.x));
    72         return true;
    73     }
    74     public:
    75     string canBeInfinite(vector <int> A, vector <int> B, vector <int> C, vector <int> D)
    76     {
    77         n=A.size();
    78         for (int i=1;i<=n;i++)
    79         {
    80             a[i].a.x=A[i-1];
    81             a[i].a.y=B[i-1];
    82             a[i].b.x=C[i-1];
    83             a[i].b.y=D[i-1];
    84         }
    85         for (int i=1;i<=n;i++)
    86             for (int j=i+1;j<=n;j++)
    87                 if (!calc(a[i],a[j])) return "Finite";
    88         sort(cover+1,cover+cnt+1);
    89         if (cover[1].first+M_PI>eps) return "Infinite";
    90         if (cover[cnt].second-M_PI<-eps) return "Infinite";
    91         double now=cover[1].second;
    92         for (int i=2;i<=cnt;i++)
    93         {
    94             if (cover[i].first-now>eps) return "Infinite";
    95             now=cover[i].second;
    96         }
    97         return "Finite";
    98     }
    99 };

    完结撒花~

  • 相关阅读:
    temp etc/hosts
    chrome 32位安装好没法访问解决命令 64位也会有这样的问题
    函数与存储过程的区别
    VS创建新的本地数据库
    主从同步
    自定义函数Function
    特殊存储过程——触发器Trigger
    存储过程Procedure
    工具:sql server profiler(分析器)
    数据表访问
  • 原文地址:https://www.cnblogs.com/Tommyr7/p/6861903.html
Copyright © 2011-2022 走看看