这是第二场比赛的。才搞完= =
A. 丁神去谷歌 2014新生暑假个人排位赛02
题目描述
丁神要去Google上班了,去之前丁神想再做一道水题,但时间不多了,所以他希望题目做起来既水又快。现在一共有 n 道题,编号从1到 n ,每道题有两个值 a 和 b , a 为做这道题需要的时间, b 为题目的“水值”,丁神希望做 b/a 最大的那题。
输入格式
输入第一行为数据组数 T(T≤10) ,接下来T组数据,每组数据中第一行为一个数 n , n 为题目的数量,接下来 n 行,每行两个正整数 a 和 b 。如果两道题 b/a 的值是一样的就输出 a 比较小的,如果还一样就输出编号比较靠前的。 1≤a,b≤109,1≤n≤100000)
输出格式
对于每组数据,输出对应的题目编号,每个输出占一行。
输入样例
1
2
3 5
4 8
输出样例
2
#include <iostream>
#include <cstdio>
using namespace std;
struct Num
{
long long top;
long long bot;
};
int t,n,Id;
Num ans,temp;
bool Dayu(Num a,Num b)
{
if( b.bot*a.top>b.top*a.bot ) return true;
if( b.bot*a.top==b.top*a.bot && a.bot<b.bot) return true;
return false;
}
int main()
{
scanf("%d",&t);
while(t--)
{
scanf("%d",&n);
scanf("%lld%lld",&temp.bot,&temp.top);
ans.bot=temp.bot;
ans.top=temp.top;
Id=1;
for(int i=2;i<=n;i++)
{
scanf("%lld%lld",&temp.bot,&temp.top);
if(Dayu(temp,ans))
{
ans.top=temp.top;
ans.bot=temp.bot;
Id=i;
}
}
printf("%d\n",Id);
}
return 0;
}
------------------------------------------------------------------------------------------
B. 丁神又去谷歌 2014新生暑假个人排位赛02
题目描述
丁神又要去Google上班了,这一次丁神想多做几道水题,并使题目的总水量最大.丁神同一时刻只能在水一道题,只有做完这道题才能得到它的水值,丁神的总时间为 t ,现在一共有 n 道题,编号从1到 n ,每道题有两个值 a 和 b , a 为做这道题需要的时间, b 为题目的水值。
输入格式
输入第一行为数据组数 T(T≤10) ,接下来 T 组数据,每组数据中第一行为两个数 t 和 n , n 为题目的数量, t 为总时间,接下来 n 行,每行两个正整数 a 和 b 。 (1≤a,t≤1000,1≤n≤100,1≤b≤1000000000)
输出格式
对于每组数据,输出对应的最大总水量,每个输出占一行。
输入样例
1
10 2
8 16
6 12
输出样例
16
裸01背包 换个变量名就行
#include <iostream>
#include <cstdio>
#include <cstring>
#define maxn 105
#define maxt 1005
#define ll long long
using namespace std;
int Test,t,n;
int a_time[maxn];
ll b_val[maxn];
ll dp[maxn][maxt];
int main()
{
scanf("%d",&Test);
while(Test--)
{
scanf("%d%d",&t,&n);
for(int i=1;i<=n;i++)
scanf("%d%lld",&a_time[i],&b_val[i]);
memset(dp,0,sizeof(dp));
for(int i=1;i<=n;i++)
for(int j=1;j<=t;j++)
{ if(j>=a_time[i])
dp[i][j]=max(dp[i-1][j],dp[i-1][j-a_time[i]]+b_val[i]);
else dp[i][j]=dp[i-1][j];
}
printf("%lld\n",dp[n][t]);
}
return 0;
}
-------------------------------------------
C. goblin 2014新生暑假个人排位赛02
题目描述
现有一段横向长度为N的山脉,其中每段有一个独一无二的高度Hi(1到N之间的正整数)。现在你想知道对于长度为N的山脉,可能有这样的山脉多少种。这样的山脉是:某个位置要么比两边的高度都低,要么比两边的高度都高。两座山脉 A和 B 不同当且仅当存在一个 i,使得 Ai≠Bi。由于这个数目可能很大,你只对它除以 P 的余数感兴趣。
输入格式
输入以EOF为结束,每组仅含一行,两个正整数 N, P。 3≤N≤4200,P≤10^9
输出格式
对于每组数据输出仅含一行,一个非负整数,表示你所求的答案对 P 取余之后的结果。
输入样例
4 7
输出样例
3
说明:共有 10 种可能的山脉,它们是:
1324 1423 2143 2314 2413
3142 3241 3412 4132 4231
就说说我的理解吧。代码见whnblog
dp方程g[i]=g[i]+c[i-1][j]*g[j]*g[i-1-j];
每次加入一个最高的棍,枚举这根棍左和右分别出现的情况
通过这道题学会了如何处理锯齿形状的数列
----------------------------------------------------------------------------
D. 学姐逗学弟 2014新生暑假个人排位赛02
题目描述
学弟们来了之后,学姐每天都非常高兴的和学弟一起玩耍。这一天,学姐想出了这样一个游戏,她画了一棵树,树上共有 n 个节点,现在学姐把 m(m≤n) 个石子随机放在节点上,每个节点可以放多个,每一次操作是指把每一个节点上的所有石子都往下移动到他某一个子节点(一个节点有多个石子可以分别移动到不同子节点),如果没有子节点则不移动,无法移动的人输。 学姐说,学弟是绅士应该让学姐先走,其实学姐已经策划好了自己一定会赢,但是这时学弟说,学姐先下那么我来画树和放石子吧,学姐惊呆了。现在她来想知道在新的图上,两人都按最优方案走,自己还能不能赢。
输入格式
输入第一行为一个整数 T 表示数据组数,接下来 T 组数据,每组开头为两个整数 n,m ,表示节点个数和石子个数, 1≤m≤n≤100000 ,接下来一行 n−1 个整数,表示2到 n 节点的父亲节点编号,接下来一行m个整数,表示每一个石子的位置。数据保证1为根节点。
输出格式
如果学姐能胜利,输出"MengMengDa!",否则输出"So sad..."。没有引号。
输入样例
1
3 1
1 1
1
输出样例
MengMengDa!
其实就是一个everysg游戏,求出step最大的有石子节点的输赢
#include <iostream>
#include <cstdio>
#include <cstring>
#define maxn 100005
using namespace std;
int Index,n,m,t,Maxstep,Maxpos;
int head[maxn],next[maxn],edge[maxn],step[maxn];
bool Vic[maxn];
int stone[maxn];
void Addedge(int a,int b)
{
Index++;
next[Index]=head[a];
edge[Index]=b;
head[a]=Index;
}
void Dfs(int src)
{
if(!head[src]) {Vic[src]=false;step[src]=1;return;}
for(int p=head[src];p;p=next[p]) Dfs(edge[p]);
bool flagVic=false;
for(int p=head[src];p;p=next[p])
if(!Vic[edge[p] ]) flagVic=true;
if(!flagVic)
{
Vic[src]=false;
step[src]=step[edge[head[src] ] ];
for(int p=head[src];p;p=next[p])
step[src]=min(step[src],step[edge[p] ]);
step[src]++;
}
else
{
Vic[src]=true;
step[src]=0;
for(int p=head[src];p;p=next[p])
if(!Vic[edge[p] ]) step[src]=max(step[src],step[edge[p] ]);
step[src]++;
}
}
int main()
{
scanf("%d",&t);
while(t--)
{
Index=0;
scanf("%d%d",&n,&m);
memset(head,0,sizeof(head));
memset(next,0,sizeof(next));
for(int i=2;i<=n;i++)
{
int temp;
scanf("%d",&temp);
Addedge(temp,i);
}
for(int i=1;i<=m;i++) scanf("%d",&stone[i]);
Dfs(1);
Maxstep=0;
for(int i=1;i<=m;i++)
if(step[stone[i]]>Maxstep)
{
Maxstep=step[stone[i]];
Maxpos=stone[i];
}
if(Vic[Maxpos]) printf("MengMengDa!\n");
else printf("So sad...\n");
}
return 0;
}
------------------------------------------------------------------------------------------------
425. 木头人足球赛
题目描述
木头人星的行动速度是地球上乌龟的 1/10 (所以可以忽略移动的速度),可是他们也热爱运动,尤其是足球。 他们的足球规则跟人类的一样,足球场尺寸为标准 105 * 68,两队各 11 名球员参赛。 假设 Mays 队的每个队员都是专业的球员,踢球都特别准。而她们的对手 Luke 队截球的规律是,如果行进的球离自己的距离不超过 d ,就可以截球成功。 现在 Mays 队的十号球员拿到了球,如果只允许一次射门,Mays 队能不能进球呢? 足球场在 xy 平面内,(0,0)至(105,68)矩形范围内,边缘与 x,y 轴平行且不能站人。其中Luke队的球门为(0, 30)-(0, 38),Mays 队的球门为(105,30)-(105, 38)
输入格式
第一行为组数 T ,对这 T 组数据,每组第一行是Mays队十号球员的坐标 x0,y0 ,接下来 11 行为 Luke 队的 1 - 11 号队员的属性 xi,yi,di , 其中 xi,yi 表示 i 号球员的坐标, di 表示 i 号球员截球能力值。 保证所有坐标不重复且都在球场范围内, x,y 为整数, d 为正实数 1.0≤d≤3.0 。
输出格式
每组数据一行,如果 Mays 队10号队员直接可以射门得分,则输出“Shoot!”;如果10号队员不能成功射门,输出"Poor Mays!".
输入样例
1
104 34
1 24 2.928
48 25 2.605
15 41 1.312
39 42 2.454
3 12 2.080
18 39 1.564
10 36 2.530
97 13 1.589
101 57 1.844
84 39 2.561
0 33 1.831
输出样例
Shoot!
计算几何啊。。。。
先求所有圆过x0,y0的切线,再求出和x=0的交点。。
于是得出每个圆在x=0上的投影,再判断这些投影是否把球门盖住
这题拿到了测试数据仍然没过。。。。总会卡在几个数据上。。。
目前还是wa的状态。。
求只菊苣来看下代码。。。。。
#include <iostream> #include <cstdio> #include <cmath> #include <algorithm> #define eps 0.0000001 using namespace std; int t,x0,Y0,Index; struct QuJianPair { double da; double xiao; }QuJian[20]; double GetK(int x,int y) { return (double)(y-Y0)/(double)(x-x0); } bool cmp(QuJianPair a,QuJianPair b) { return a.da>b.da; } int main() { // freopen("in.txt","r",stdin); // freopen("out1.txt","w",stdout); scanf("%d",&t); while(t--) { scanf("%d%d",&x0,&Y0); int tempx,tempy; double r; bool MaysFlag=true; Index=0; for(int i=1;i<=11;i++) { scanf("%d%d%lf",&tempx,&tempy,&r); if( (double)((tempx-x0)*(tempx-x0)+(tempy-Y0)*(tempy-Y0)) < r*r +eps) {MaysFlag=false;break;} if((double)tempx > x0+r) continue; double a=(double)(tempx-x0)*(tempx-x0) - r*r; double b=(double)2*(tempx-x0)*(Y0-tempy); double c=(double)(Y0-tempy)*(Y0-tempy) - r*r; double solk1=((-b)+sqrt(b*b-4*a*c))/(2*a); double solk2=((-b)-sqrt(b*b-4*a*c))/(2*a); if((double)tempx +eps< x0-r) { Index++; QuJian[Index].da=min(solk1,solk2)*(0-x0)+Y0; QuJian[Index].xiao=max(solk1,solk2)*(0-x0)+Y0; } else { if((double)tempx > x0-r +eps) { if((double)tempy > Y0 ) { Index++; QuJian[Index].da=68; QuJian[Index].xiao=min(solk1,solk2)*(0-x0)+Y0; } else { Index++; QuJian[Index].da=max(solk1,solk2)*(0-x0)+Y0; QuJian[Index].xiao=0; } } else { if((double)tempy > Y0 ) { Index++; QuJian[Index].da=68; if(abs(solk1)<1000000) QuJian[Index].xiao=solk1*(0-x0)+Y0; else QuJian[Index].xiao=solk2*(0-x0)+Y0; } else { Index++; if(abs(solk1)<1000000) QuJian[Index].da=solk1*(0-x0)+Y0; else QuJian[Index].da=solk2*(0-x0)+Y0; QuJian[Index].xiao=0; } } } } sort(QuJian+1,QuJian+1+Index,cmp); if(MaysFlag) { if(QuJian[1].da<38) printf("Shoot!\n"); else { bool MaysJin=false; for(int i=2;i<Index;i++) { bool flag=false; int pos; for(int j=1;j<i;j++) if(QuJian[j].xiao<QuJian[i].da + eps) {flag=true;pos=j;}//dangzhu if(!flag && QuJian[i].da<38 && QuJian[pos].xiao>30) {printf("Shoot!\n");MaysJin=true;break;} } if((!MaysJin)) { bool tempflag=true;//meidangzhu for(int i=1;i<=Index;i++) if(QuJian[i].xiao<30+eps) {printf("Poor Mays!\n");tempflag=false;break;}//dangzhule if(tempflag) printf("Shoot!\n"); } } } else printf("Poor Mays!\n"); } return 0; }