2019 ICPC Asia Nanjing Regional
作者:互联网
A题
-
题意
-
思路
就找最大的集合,不存在 2 2 2 倍关系的那个就是答案。 -
代码
int n;cin>>n;
if (n % 2 == 0) {
cout << n/2+1 <<endl;
} else {
cout << n/2+2 <<endl;
}
H题
- 题意
王子想要娶公主,但是需要完成一个挑战:在一些房间中找出公主在哪。
每个房间有一个人,他们彼此知道谁在哪个房间。可以问他们三种问题:
- 你是谁?
- 在某个房间是谁?
- 公主在哪个房间?
有三类人,一类一定说真话,一类一定说假话,一类可能说真话可能说假话。
王子知道这三类人的人数分别为 a, b, c,求能否通过问一些问题找到公主在哪,如果能,输出最少需要的问题数。
- 思路
太狗了吧这题
1 , 0 , 0 1,0,0 1,0,0 这种情况为啥不用问就可以了,这也太好了吧,难道公主直接看着没有人反对直接找他去了嘛。呜呜呜 - 代码
if (!b&&!c&&a==1) {
cout<<"YES"<<endl;
cout<<0<<endl; return;
}//死活没想到
if (a <= b+c) {
cout<<"NO"<<endl;
} else {
cout<<"YES"<<endl;
cout<<2*(b+c)+1<<endl;
}
这要是在比赛中不得被队友打死。
K题
- 题意
- 思路
这就是个简单几何题。
如果 A A A 点不在三角形的三边,那么就是 − 1 -1 −1 ;如果在的话,可以知道必有解。然后如果点 A A A 在边 a c ac ac 上,如果 a A aA aA > A c Ac Ac,那么点 B B B 可以确定在某一条边上,因此面积的变化具有单调性,所有可以二分处理。 - 代码
#include <bits/stdc++.h>
using namespace std;
int n, m, T;
// 计算几何模板
const double eps = 1e-8;
// 和0做比较
int sgn(double x) {
if (fabs(x) < eps) return 0; // =0
if (x < 0)
return -1; // < 0
else
return 1; // > 0
}
struct Point {
double x, y;
Point() {}
Point(double _x, double _y) {
x = _x;
y = _y;
}
void input() { scanf("%lf%lf", &x, &y); }
void output() { printf("%.10f %.10f\n", x, y); }
bool operator<(Point b) const {
return sgn(x - b.x) == 0 ? sgn(y - b.y) < 0 : x < b.x;
}
Point operator-(const Point &b) const { return Point(x - b.x, y - b.y); }
//叉积
double operator^(const Point &b) const { return x * b.y - y * b.x; }
//点积
double operator*(const Point &b) const { return x * b.x + y * b.y; }
//返回向量长度
double len() {
// hypot(x, y), 即sqrt(x * x + y * y)
return hypot(x, y); //库函数
}
//返回两点的距离
double distance(Point p) { return hypot(x - p.x, y - p.y); }
Point operator+(const Point &b) const { return Point(x + b.x, y + b.y); }
Point operator*(const double &k) const { return Point(x * k, y * k); }
Point operator/(const double &k) const { return Point(x / k, y / k); }
//计算pa和pb的夹角, 就是求这个点看a,b 所成的夹角的弧度
};
struct Line {
Point s, e;
Line() {}
// 两点确定一条线段
Line(Point _s, Point _e) {
s = _s;
e = _e;
}
// 点在线段上的判断
bool pointonseg(Point p) {
return sgn((p - s) ^ (e - s)) == 0 && sgn((p - s) * (p - e)) <= 0;
}
};
double getarea(Point a, Point b, Point c) {
double sum = 0;
sum += a.operator^(b) + b.operator^(c) + c.operator^(a);
return fabs(sum) / 2;
}
Point get_mid(Point l, Point r) {
return (l + r) * 0.5;
}
int main() {
Point a, b, c, e, s;
Line ab, bc, ac;
cin >> T;
while (T--) {
a.input(), b.input(), c.input(), e.input();
double tran_area = getarea(a, b, c) / 2;
ab = Line(a, b), bc = Line(b, c), ac = Line(a, c);
if (!ab.pointonseg(e) && !ac.pointonseg(e) && !bc.pointonseg(e)) {
puts("-1");
continue;
}
if (ab.pointonseg(e)) {
double ae = a.distance(e), eb = b.distance(e);
if (ae > eb) {
Point l = a, r = c;
Point mid = get_mid(l, r);
int time = 1000;
while (time--) {
mid = get_mid(l, r);
int flg = sgn(getarea(a, e, mid) - tran_area);
if (flg == 0) break;
else if (flg > 0) r = mid;
else l = mid;
}
mid.output();
} else {
Point l = b, r = c;
Point mid = get_mid(l, r);
int time = 1000;
while (time--) {
mid = get_mid(l, r);
int flg = sgn(getarea(b, e, mid) - tran_area);
if (flg == 0) break;
else if (flg > 0) r = mid;
else l = mid;
}
mid.output();
}
} else if (bc.pointonseg(e)) {
double be = b.distance(e), ce = c.distance(e);
if (be > ce) {
Point l = b, r = a;
int time = 1000;
Point mid = get_mid(l, r);
while (time--) {
mid = get_mid(l, r);
int flg = sgn(getarea(b, e, mid) - tran_area);
if (flg == 0) break;
else if (flg > 0) r = mid;
else l = mid;
}
mid.output();
} else {
Point l = c, r = a;
int time = 1000;
Point mid = get_mid(l, r);
while (time--) {
mid = get_mid(l, r);
int flg = sgn(getarea(e, c, mid) - tran_area);
if (flg == 0) break;
else if (flg > 0) r = mid;
else l = mid;
}
mid.output();
}
} else if (ac.pointonseg(e)) {
double ae = e.distance(e), ec = c.distance(e);
if (ae < ec) {
Point l = c, r = b;
Point mid = get_mid(l, r);
int time = 1000;
while (time--) {
mid = get_mid(l, r);
int flg = sgn(getarea(e, c, mid) - tran_area);
if (flg == 0) break;
else if (flg > 0) r = mid;
else l = mid;
}
mid.output();
} else {
Point l = a, r = b;
Point mid = get_mid(l, r);
int time = 1000;
while (time--) {
mid = get_mid(l, r);
int flg = sgn(getarea(e, a, mid) - tran_area);
if (flg == 0) break;
else if (flg > 0) r = mid;
else l = mid;
}
mid.output();
}
}
}
return 0;
};
- 代码2
#include <bits/stdc++.h>
using namespace std;
typedef double ld;
ld eps = 1e-8;
struct Point{
ld x, y;
}a, b, c, p, q;
ld area;
ld ab, ac, bc, ap, bp;
bool onSegment(Point Pi, Point Pj, Point Q)
{
if((Q.x - Pi.x) * (Pj.y - Pi.y) == (Pj.x - Pi.x) * (Q.y - Pi.y) //叉乘
//保证Q点坐标在pi,pj之间
&& min(Pi.x , Pj.x) <= Q.x && Q.x <= max(Pi.x , Pj.x)
&& min(Pi.y , Pj.y) <= Q.y && Q.y <= max(Pi.y , Pj.y))
return true;
else
return false;
}
ld dist(Point a, Point b){
return sqrt((a.x-b.x)*(a.x-b.x)+(a.y-b.y)*(a.y-b.y));
}
bool check(ld mid, ld sinb)
{
ld are = sinb*(bp)*(bc-mid)/2;
if(are*2.0 >= area) return 0;
return 1;
}
void solve()
{
scanf("%lf%lf%lf%lf%lf%lf%lf%lf", &a.x, &a.y, &b.x, &b.y, &c.x, &c.y, &p.x, &p.y);
//cin>>a.x>>a.y>>b.x>>b.y>>c.x>>c.y>>p.x>>p.y;
if(!onSegment(a, b, p)&&!onSegment(b, c, p)&&!onSegment(a, c, p))
{
puts("-1");
return;
}
//先看看会不会在某个点上
if(p.x == a.x && p.y == a.y)
{
//输出bc中点
q.x = (b.x+c.x)/2.0;
q.y = (b.y+c.y)/2.0;
//cout << setprecision(10) << q.x << " " << q.y << endl;
printf("%.10f %.10f\n", q.x, q.y);
return;
}
else if(p.x == b.x && p.y == b.y)
{
//ac中点
q.x = (a.x+c.x)/2.0;
q.y = (a.y+c.y)/2.0;
//cout << setprecision(10) << q.x << " " << q.y << endl;
printf("%.10f %.10f\n", q.x, q.y);
return;
}
else if(p.x == c.x && p.y == c.y)
{
//ab中点
q.x = (a.x+b.x)/2.0;
q.y = (a.y+b.y)/2.0;
// cout << setprecision(10) << q.x << " " << q.y << endl;
printf("%.10f %.10f\n", q.x, q.y);
return;
}
//把点弄到ab上
if(onSegment(a, b, p)) {}
else if(onSegment(b, c, p)) swap(a, c);
else if(onSegment(a, c, p)) swap(b, c);
//距离b更近一点
if(dist(a, p) > dist(b, p)) swap(a, b);
//开始搞
ab = dist(a, b);
ac = dist(a, c);
bc = dist(b, c);
ap = dist(a, p);
bp = dist(b, p);
ld p = (ab+bc+ac)/(ld)2.0;
area = sqrt(p*(p-ab)*(p-bc)*(p-ac));
ld sina = area*2/ab/bc;
//area = ab*bc*sinb/2
//sina = area*2/ab/bc
ld l = 0.0, r = bc;
while(l+eps < r)
{
ld mid = (l+r)/(ld)2.0;
if(check(mid, sina)) r = mid;
else l = mid;
}
ld len = l;
//输出点
q.x = (b.x-c.x)*len/bc+c.x;
q.y = (b.y-c.y)*len/bc+c.y;
//cout << setprecision(10) << q.x << " " << q.y << endl;
printf("%.10f %.10f\n", q.x, q.y);
return;
}
int main()
{
int T; scanf("%d", &T);
while(T--) solve();
return 0;
}
C题
- 题意
找满足题意的路径的数目。 - 思路
相邻的两个点如果权值相差为 1 1 1,则从小的向大的连边。然后最终连成的是一个 D A G DAG DAG,在 D A G DAG DAG 上面按照拓扑序 D P DP DP 即可。 - 代码
#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>
#include <queue>
using namespace std;
const int N = 1010, mod = 1e9 + 7;
typedef pair<int,int> pii;
int n, m;
int g[N][N], in[N][N], out[N][N], f[N][N][5];
int dx[4] = {0,1,0,-1}, dy[4] = {1,0,-1,0};
void topsort()
{
queue<pii> que;
for(int i=1;i<=n;i++)
for(int j=1;j<=m;j++)
if(!in[i][j])
{
que.push({i,j});
f[i][j][1] = 1;
}
while(que.size())
{
auto t = que.front();
que.pop();
int x = t.first, y = t.second;
for(int i=0;i<4;i++)
{
int tx = x + dx[i], ty = y + dy[i];
if(tx<1||tx>n||ty<1||ty>m) continue;
if(g[tx][ty]==g[x][y]+1)
{
f[tx][ty][2] = (f[tx][ty][2] + f[x][y][1]) % mod;
f[tx][ty][3] = (f[tx][ty][3] + f[x][y][2]) % mod;
f[tx][ty][4] = (f[tx][ty][4] + f[x][y][3] + f[x][y][4]) % mod;
if(--in[tx][ty]==0) que.push({tx,ty});
}
}
}
}
int main()
{
scanf("%d%d",&n,&m);
for(int i=1;i<=n;i++)
for(int j=1;j<=m;j++)
scanf("%d",&g[i][j]);
for(int i=1;i<=n;i++)
for(int j=1;j<=m;j++)
for(int k=0;k<4;k++)
{
int tx = i + dx[k], ty = j + dy[k];
if(tx<1||tx>n||ty<1||ty>m) continue;
if(g[tx][ty]==g[i][j]+1) out[i][j] ++;
if(g[tx][ty]==g[i][j]-1) in[i][j] ++;
}
int res = 0;
topsort();
for(int i=1;i<=n;i++)
for(int j=1;j<=m;j++)
if(!out[i][j])
res = (res + f[i][j][4]) % mod;
printf("%d\n",res);
return 0;
}
标签:return,Point,int,Regional,mid,Nanjing,else,2019,flg 来源: https://blog.csdn.net/qq_46264636/article/details/121178446