第四届福建省大学生程序设计竞赛

Tag Pro.ID Problem Title Ratio(AC/Submit)
 1Forever 0.518.92%(7/37)
 2Sub-Bipartite Graph50.00%(1/2)
 3Center of a Tree0.00%(0/2)
 4Board Game54.55%(6/11)
 5Shooting Game37.84%(14/37)
 6Rock-Paper-Scissors Game50.00%(1/2)
 7Easy Game73.86%(113/153)
 8A-B Game43.46%(103/237)
 9Moon Game22.98%(54/235)
 10Reverse Game40.00%(6/15)
 11Fire Game17.59%(38/216)
 12OOXX Game60.12%(98/163)
现场6题。。赛后想其实能出7题的。。

开始先是切了3题最水的题目。。都是1A

G题:

#include <stdio.h>
#include <string.h>
const int N = 10100;
const char ans[2][10] = {"Even", "Odd"};
int t;
char str[N];

int main() {
	int cas = 0;
	scanf("%d", &t);
	while (t--) {
		scanf("%s", str);
		printf("Case %d: %s\n", ++cas, ans[strlen(str) % 2]);

	}
	return 0;
}
H题:

#include <stdio.h>
#include <string.h>

int t;
long long a, b;

int main() {
	int cas = 0;
	scanf("%d", &t);
	while (t--) {
		int ans = 0;
		scanf("%lld%lld", &a, &b);
		while (a > b) {
			a -= (a - 1) / 2;
			ans ++;
		}
		printf("Case %d: %d\n", ++cas, ans);
	}
	return 0;
}

L题:

#include <stdio.h>
#include <string.h>
const int N = 105;
const char ANS[2][20] = {"Fat brother", "Maze"};
int t;
int n, m;
char str[N][N];

int main() {
	int cas = 0;
	scanf("%d", &t);
	while (t--) {
		int ans = 0;
		scanf("%d%d", &n, &m);
		for (int i = 0; i < n; i ++) {
			scanf("%s", &str[i]);
			for (int j = 0; j < m; j ++)
				if (str[i][j] == 'O')
					ans ++;
		}
		printf("Case %d: %s\n", ++cas, ANS[ans % 2]);
	}
	return 0;
}

然后就看到K题搜索题,思路很明确。广搜每次2个草的结点入队,然后枚举。。现场因为一个下标错了WA了次。。也是唯一一次WA。

K题:

#include <stdio.h>
#include <string.h>
#include <queue>
using namespace std;
#define min(a,b) (a)<(b)?(a):(b)
#define max(a,b) (a)>(b)?(a):(b)
#define INF 0x3f3f3f3f
const int N = 15;
const int d[4][2] = {{1, 0}, {-1, 0}, {0, 1}, {0, -1}};

int t, n, m, res[N][N], num, vis[N][N];
char map[N][N];

struct Node {
	int x, y;
} q, p;

void init() {
	num = 0;
	scanf("%d%d%*c", &n, &m);
	for (int i = 0; i < n; i ++) {
		gets(map[i]);
		for (int j = 0; j < m; j ++)
			if (map[i][j] == '#')
				num++;
	}
}

int bfs(int x1, int y1, int x2, int y2) {
	int ans = 0;
	memset(res, INF, sizeof(res));
	memset(vis, 0, sizeof(vis));
	queue<Node>Q;
	res[x1][y1] = 0; res[x2][y2] = 0;
	q.x = x1; q.y = y1; Q.push(q); q.x = x2; q.y = y2; Q.push(q);
	while (!Q.empty()) {
		q = Q.front(); Q.pop();
		vis[q.x][q.y] = 0;
		ans = max(ans, res[q.x][q.y]);
		for (int i = 0; i < 4; i ++) {
			p.x = q.x + d[i][0];
			p.y = q.y + d[i][1];
			if (p.x >= 0 && p.x < n && p.y >= 0 && p.y < m && map[p.x][p.y] == '#') {
				if (res[p.x][p.y] > res[q.x][q.y] + 1 && !vis[p.x][p.y]) {
					res[p.x][p.y] = res[q.x][q.y] + 1;
					vis[p.x][p.y] = 1;
					Q.push(p);
				}
			}
		}
	}
	for (int k = 0; k < n; k ++)
		for (int l = 0; l < m; l ++)
			if (map[k][l] == '#' && res[k][l] == INF)
				return INF;
	return ans;
}

void solve() {
	int ans = INF;
	if (num <= 2) ans = 0;
	else {
		int x1, y1, x2, y2;
		for (int i = 0; i < n * m; i ++) {
			x1 = i / m; y1 = i % m; if (map[x1][y1] != '#') continue;
			for (int j = i + 1; j < n * m; j ++) {
				x2 = j / m; y2 = j % m; if (map[x2][y2] != '#') continue;
				int t = bfs(x1, y1, x2, y2);
				ans = min(ans, t);
			}
		}
	}
	if (ans == INF) printf("-1\n");
	else printf("%d\n", ans);
}

int main() {
	int cas = 0;
	scanf("%d", &t);
	while (t--) {
		init();
		printf("Case %d: ", ++cas);
		solve();
	}
	return 0;
}

4题之后,然后是突然灵光一闪有了I题的解法:判断方法是点有没在其他三点之内。这样一来就很水了

I题:

#include <stdio.h>
#include <string.h>
#include <math.h>
const int N = 35;

struct Point {
	int x, y;
} p[N];

int t, n;

void init() {
	scanf("%d", &n);
	for (int i = 0; i < n; i ++)
		scanf("%d%d", &p[i].x, &p[i].y);
}

double area(int a, int b, int c) {
	return p[a].x * p[b].y + p[c].x * p[a].y + p[b].x * p[c].y - p[c].x * p[b].y - p[a].x * p[c].y - p[b].x * p[a].y;
}

bool OK(int a, int b, int c, int d) {
	double sum = fabs(area(a, b, d)) + fabs(area(a, c, d)) + fabs(area(a, b, c));
	double save = fabs(area(b, c, d));
	if (fabs(sum - save) < 1e-9) return true;
	return false;
}

bool judge(int i, int j, int k, int l) {
	if (OK(i, j, k, l)) return false;
	if (OK(j, i, k, l)) return false;
	if (OK(k, j, i, l)) return false;
	if (OK(l, j, k, i)) return false;
	return true;
}

int solve() {
	int ans = 0;
	for (int i = 0; i < n; i ++)
		for (int j = i + 1; j < n; j ++)
			for (int k = j + 1; k < n; k ++)
				for (int l = k + 1; l < n; l ++) {
					if (judge(i, j, k, l))
						ans++;
				}
	return ans;
}

int main() {
	int cas = 0;
	scanf("%d", &t);
	while (t--) {
		init();
		printf("Case %d: %d\n", ++cas, solve());

	}
	return 0;
}

之后就想A题和E题。。A题最终想出了点的构造方式,写起来就很水了。。

A题:

#include <stdio.h>
#include <string.h>
#include <math.h>
const int N = 110;
int t, n;
double x[N], y[N];

void init() {
	x[1] = 0; y[1] = 0;
	x[2] = 0; y[2] = 1;
	x[3] = sqrt(3) / 2; y[3] = 0.5;
	x[4] = sqrt(3) / 2 - 1; y[4] = 0.5;
	for (int i = 5; i <= 100; i ++) {
		x[i] = x[2] + ((i - 4) * 0.005);
		y[i] = sqrt(1 - x[i] * x[i]);
	}
}

int main() {
	init();
	scanf("%d", &t);
	while (t--) {
		scanf("%d", &n);
		if (n < 4) printf("No\n");
		else {
			printf("Yes\n");
			for (int i = 1; i <= n; i ++)
				printf("%.6lf %.6lf\n", x[i], y[i]);
		}
	}
	return 0;
}

最后剩1个小时想E题,想到是贪心的区间选点,但是没想到构造区间的方法,是去解二元方程组。。

E题:

#include <stdio.h>
#include <string.h>
#include <math.h>
#include <algorithm>
using namespace std;
const int N = 100005;

struct Point {
	double x, y, z;
	double xk, yk, zk;
	double s, e;
	int vis;
} p[N];

int t, n, ansn, ansc;
double r;

void init() {
	ansn = ansc = 0;
	memset(p, 0, sizeof(p));
	scanf("%d%lf", &n, &r);
	for (int i = 0; i < n; i ++) {
		scanf("%lf%lf%lf%lf%lf%lf", &p[i].x, &p[i].y, &p[i].z, &p[i].xk, &p[i].yk, &p[i].zk);
	}
}

bool cmp(Point a, Point b) {
	return a.e < b.e;
}
void solve() {
	ansn = n;
	for (int i = 0; i < n; i ++) {
		double a = p[i].xk * p[i].xk + p[i].yk * p[i].yk + p[i].zk * p[i].zk;
		double b = 2 * p[i].x * p[i].xk + 2 * p[i].y * p[i].yk + 2 * p[i].z * p[i].zk;
		double c = p[i].x * p[i].x + p[i].y * p[i].y + p[i].z * p[i].z - r * r;
		double dlt =b * b - 4 * a * c;
		if (dlt < 0) {
			ansn--;
			continue;
		}
		double k1 = (-b + sqrt(dlt)) / (2 * a);
		double k2 = (-b - sqrt(dlt)) / (2 * a);
		if (k1 < 0 && k2 < 0) {
			ansn--;
			continue;
		}
		if (k2 < k1) {
			if (k2 < 0) k2 = 0;
			p[i].s = k2; p[i].e = k1;
		}
		else {
			if (k1 < 0) k1 = 0;
			p[i].s = k1; p[i].e = k2;
		}
		p[i].vis = 1;
	}
	sort(p, p + n, cmp);
	double c = -1000000000;
	for (int ii = 0; ii < n; ii ++) {
		if (!p[ii].vis) continue;
		if (p[ii].s > c) {
			c = p[ii].e;
			ansc ++;
		}
	}
}

int main() {
	int cas = 0;
	scanf("%d", &t);
	while (t--) {
		init();
		solve();
		printf("Case %d: %d %d\n", ++cas, ansn, ansc);
	}
	return 0;
}

E题后面在FZU上时间改成1秒了。。要用输入外挂才能过了。。。

总结:这次比赛,还是比较稳的,基本1A,不求很快,发挥也还行。。运气也还不错(最后是金奖,虽然是最后一名哈哈哈。),也有点遗憾最后第7题没出。总之结果还是很满意了。。再接再厉

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值