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|)左右吧,代码如下:
#include <bits/stdc++.h>
using namespace std;
class PowerOfThree
{
public:
string ableToGet(int x, int y)
{
x=abs(x),y=abs(y);
bool check=true;
while (x!=||y!=)
{
if ((x%==)+(y%==)!=) check=false;
if (x%==) x=(x+)/; else x=x/;
if (y%==) y=(y+)/; else y=y/;
}
if (check) return "Possible"; else return "Impossible";
}
};
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),代码如下:
#include <bits/stdc++.h>
#define Maxn 1007
#define inf 1000000007
using namespace std;
int n,cnt,ans=inf,m;
int last[Maxn],other[Maxn],pre[Maxn],sum[Maxn],size[Maxn];
int f[*Maxn][*Maxn];
int temp[*Maxn];
bool fox[Maxn];
class FoxConnection
{
void insert(int u, int v)
{
other[++cnt]=v,pre[cnt]=last[u],last[u]=cnt;
}
void dfs(int u, int fa)
{
size[u]=fox[u];
int cur[*Maxn];
memset(cur,,sizeof(cur));
for (int q=last[u];q;q=pre[q])
{
int v=other[q];
if (v!=fa)
{
dfs(v,u);
for (int i=;i<=m;i++) temp[i]=inf;
for (int i=;i<=m;i++)
for (int j=;j<=m-i;j++)
temp[i+j]=min(temp[i+j],cur[i]+f[v][j]+abs(size[v]-j));
for (int i=;i<=m;i++) cur[i]=temp[i];
size[u]+=size[v];
}
}
f[u][]=cur[];
for (int i=;i<=m;i++) f[u][i]=cur[i-];
}
int solve(int rt)
{
for (int i=;i<=n;i++)
for (int j=;j<=*n;j++)
f[i][j]=inf;
dfs(rt,-);
return f[rt][m];
}
public:
int minimalDistance(vector <int> A, vector <int> B, string haveFox)
{
n=A.size()+;
for (int i=;i<n;i++) fox[i+]=(haveFox[i]=='Y');
m=;
for (int i=;i<=n;i++) if (fox[i]) ++m;
for (int i=;i<n-;i++)
insert(A[i],B[i]),insert(B[i],A[i]);
for (int i=;i<=n;i++)
ans=min(ans,solve(i));
return ans;
}
};
Hard(1000pts):
这个计算几何题怎么比medium思路简单多了呢。。。
题目大意:给了你n条线段,它们可能有交点,可能有重合,现在把它们视为一个模块,有一张10^9*10^9的长方形纸片,现在复制若干遍这个模块,要求任意两个模块不能相交,要求判断是否可以复制无穷多份。数据满足n<=50。
这题的思路还是很简单的吧,如果能够复制无数份,那么一定是能够往某个方向移动了很小很小的距离,
我们先把所有直线两两处理,
如果重合,直接不用管;
如果没有交点,直接不用管;
如果有一个交点,而且交点不是直线的端点,直接有穷个返回答案;
如果有一个交点,而且交点是直线的端点,那么那个方向一定有角度限制,预处理出角度限制。
所有直线两两处理完了之后,把所有角度限制从小到大扫一遍,然后判定一下就做完了。
时间复杂度O(n^2),代码如下:
#include <bits/stdc++.h>
#define eps 1e-9
#define Maxn 107
using namespace std;
int n,cnt=;
struct point {double x,y;};
struct line {point a,b;};
line a[Maxn];
pair<double,double> cover[Maxn*Maxn*];
class FamilyCrest
{
double cross(double x1 ,double y1, double x2, double y2)
{
return (x1*y2-x2*y1);
}
bool samepoint(point a, point b)
{
//check if point a and point b are the same point
if (fabs(a.x-b.x)<eps&&fabs(a.y-b.y)<eps) return true;
return false;
}
bool sameline(line a, line b)
{
//check if line a and line b are the same line
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);
if (fabs(res)<eps) return true;
return false;
}
double sameposition(line a, line b)
{
//check if the whole segment b is on the same direction of line a
//answer>0 means segment b is on the same direction of line a
//answer<0 means segment b has a same point with line a
//answer=0 means segment b has an end point on the line a
double res,res1,res2;
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);
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);
res=res1*res2;
return res;
}
void updata(double l, double r)
{
if (l<r)
{
cover[++cnt].first=l,cover[cnt].second=r;
} else
{
cover[++cnt].first=l,cover[cnt].second=M_PI;
cover[++cnt].first=-M_PI,cover[cnt].second=r;
}
}
bool calc(line a, line b)
{
//segment a and segment b are on the same line
if (sameline(a,b)) return true;
//segment a and segment b don't have a same point
if (sameposition(a,b)>eps) return true;
if (sameposition(b,a)>eps) return true;
//segment a and segment b have a same point which is not an end point
if (sameposition(a,b)<-eps) return false;
if (sameposition(b,a)<-eps) return false;
//segment a and segment b have a same point which is an end point
point O,A,B;
//point O is the end point
if (samepoint(a.a,b.a)) O=a.a,A=a.b,B=b.b; else
if (samepoint(a.a,b.b)) O=a.a,A=a.b,B=b.a; else
if (samepoint(a.b,b.a)) O=a.b,A=a.a,B=b.b; else
if (samepoint(a.b,b.b)) O=a.b,A=a.a,B=b.a;
if (cross(A.x-O.x,B.x-O.x,A.y-O.y,B.y-O.y)>eps) swap(A,B);
updata(atan2(A.y-O.y,A.x-O.x),atan2(O.y-B.y,O.x-B.x));
updata(atan2(O.y-A.y,O.x-A.x),atan2(B.y-O.y,B.x-O.x));
return true;
}
public:
string canBeInfinite(vector <int> A, vector <int> B, vector <int> C, vector <int> D)
{
n=A.size();
for (int i=;i<=n;i++)
{
a[i].a.x=A[i-];
a[i].a.y=B[i-];
a[i].b.x=C[i-];
a[i].b.y=D[i-];
}
for (int i=;i<=n;i++)
for (int j=i+;j<=n;j++)
if (!calc(a[i],a[j])) return "Finite";
sort(cover+,cover+cnt+);
if (cover[].first+M_PI>eps) return "Infinite";
if (cover[cnt].second-M_PI<-eps) return "Infinite";
double now=cover[].second;
for (int i=;i<=cnt;i++)
{
if (cover[i].first-now>eps) return "Infinite";
now=cover[i].second;
}
return "Finite";
}
};
完结撒花~
Topcoder SRM 604 div1题解的更多相关文章
- Topcoder SRM 602 div1题解
打卡- Easy(250pts): 题目大意:rating2200及以上和2200以下的颜色是不一样的(我就是属于那个颜色比较菜的),有个人初始rating为X,然后每一场比赛他的rating如果增加 ...
- Topcoder SRM 607 div1题解
好久没来写了,继续继续... Easy(250pts): //前方请注意,样例中带有zyz,高能预警... 题目大意:给你一个字符串,中间有一些是未知字符,请你求出这个字符串的回文子串个数的期望值.数 ...
- Topcoder SRM 608 div1 题解
Easy(300pts): 题目大意:有n个盒子,一共有S个苹果,每个盒子有多少个苹果不知道,但是知道每个盒子的苹果下限和上限.现在要至少选择X个苹果,问如果要保证无论如何都能获得至少X个苹果,至少需 ...
- Topcoder SRM 606 div1题解
打卡! Easy(250pts): 题目大意:一个人心中想了一个数,另一个人进行了n次猜测,每一次第一个人都会告诉他实际的数和猜测的数的差的绝对值是多少,现在告诉你所有的猜测和所有的差,要求你判断心中 ...
- Topcoder SRM 605 div1 题解
日常打卡- Easy(250pts): 题目大意:你有n种汉堡包(统统吃掉-),每一种汉堡包有一个type值和一个taste值,你现在要吃掉若干个汉堡包,使得它们taste的总和*(不同的type值的 ...
- Topcoder SRM 603 div1题解
昨天刚打了一场codeforces...困死了...不过赶在睡前终于做完了- 话说这好像是我第一次做250-500-1000的标配耶--- Easy(250pts): 题目大意:有一棵树,一共n个节点 ...
- Topcoder SRM 601 div1题解
日常TC计划- Easy(250pts): 题目大意:有n个篮子,每个篮子有若干个苹果和橘子,先任取一个正整数x,然后从每个篮子中选出x个水果,把nx个水果放在一起,输出一共有多少种不同的组成方案.其 ...
- Topcoder SRM 600 div1题解
日常TC计划正式启动! Easy(250pts): 题目大意:给你一个集合,里面一堆数,初始数为0,给你一个目标数,你可以选择集合中若干个数进行OR操作来得到目标数.问至少删去多少个数,使得你永远无法 ...
- Topcoder SRM 643 Div1 250<peter_pan>
Topcoder SRM 643 Div1 250 Problem 给一个整数N,再给一个vector<long long>v; N可以表示成若干个素数的乘积,N=p0*p1*p2*... ...
随机推荐
- 【Python 2 到 3 系列】 此整型非彼整型
v2.2 (2.x)以后,python支持不会溢出的 long 型. v3.0后,确切的讲, int 型(依赖运行环境C编译器中long型的精度)消失了,long型替代 int 型,成为新的.不依赖运 ...
- jQuery-laye插件实现 弹框编辑,异步验证,form验证提交
代码中用到了 jQuery的ajax异步处理,each()循环,submit()页面验证提交form表单,prepend()追加标签,laye插件的弹框效果(如有其它弹框效果可参考官网:http:// ...
- Hive学习路线图
- 数据分析处理库Pandas——数值运算
求和 对每行或每列求和. 均值 对每行或每列求均值. 最大最小值 对每行或每列求最大值或最小值. 中位数 对每行或每列求中位数. 相关系数和协方差 先导入一个DataFram结构的数据,再对这些数据计 ...
- ERROR 1005 (HY000): Can't create table 'students.#sql-d9
今天在创建外键的时候出现以下错误 ERROR 1005 (HY000): Can't create table 'students.#sql-d99_3' (errno: 150) 格式 ...
- 如何查询进程中占用CPU的线程
top -c 命令查找进程PID top -Hp PID 找进程中的线程号 echo %x 线程号 将线程转换成16进制 jstack PID |grep ...
- 翻译 | “扩展asm”——用C表示操作数的汇编程序指令
本文翻译自GNU关于GCC7.2.0版本的官方说明文档,第6.45.2小节.供查阅讨论,如有不当处敬请指正…… 通过扩展asm,可以让你在汇编程序中使用C中的变量,并从汇编代码跳转到C语言标号.在汇编 ...
- Android 中运行时权限获取联系人信息 Demo
代码比较简单... AndroidManifest.xml <?xml version="1.0" encoding="utf-8"?> <m ...
- 【UE4】二十三、UE4笔试面试题
在CSDN博客看到的,带着这些问题,多多留意,正所谓带着问题学习. 一. 1.Actor的EndPlay事件在哪些时候会调用? 2.BlueprintImplementableEvent和Bluepr ...
- Android 懒加载简单介绍
1.懒加载介绍 1.1.效果预览 1.2.效果讲解 当页面可见的时候,才加载当前页面. 没有打开的页面,就不会预加载. 说白了,懒加载就是可见的时候才去请求数据. 1.3.懒加载文章传送门 参考文章: ...