因为是新生选拔赛所以题目总体不难,但是不乏坑题(数学题和物理题)
题目都是中文题,只要题目没有歧义我基本只会讲解法。
bfs,设一个数组vis[i][j]表示从起点到(i,j)的最小数值,然后bfs就行了。
#include<iostream>
#include<string>
#include<cstring>
#include<vector>
#include<map>
#include<algorithm>
#include<queue>
#include<set>
#include<cstdio>
#include<functional>
#include<iomanip>
#include<cmath>
#include<stack>
#include<iomanip>
#include<functional>
#include <iomanip>
using namespace std;
typedef long long LL;
typedef unsigned long long ull;
const int maxn = (int)1e5 + 10;
const int BN = 30;
const int inf = 0x3f3f3f3f;
const LL INF = 0x3f3f3f3f3f3f3f3f;
const int mod = 1000000007;
const double eps = 1e-6;
const double r = 6371009;
const double PI = acos(-1);
struct nodes {
int x, y;
nodes(int _x = 0, int _y = 0) :x(_x), y(_y) {}
};
int vis[111][111];
int mp[111][111], n;
int dx[] = { 0,0,1,-1 }, dy[] = { 1,-1,0,0 };
nodes st, en;
bool check(int x, int y) {
if (x < 0 || y < 0 || x >= n || y >= n) return true;
return false;
}
void bfs() {
memset(vis, 0x3f, sizeof(vis));
queue<nodes>que;
que.push(st);
vis[st.x][st.y] = 0;
while (!que.empty()) {
nodes tmp = que.front();
que.pop();
for (int i = 0; i < 4; i++) {
int tx = tmp.x + dx[i], ty = tmp.y + dy[i];
if (check(tx, ty))continue;
if (tx == en.x&&ty == en.y){
vis[tx][ty] = min(vis[tx][ty], vis[tmp.x][tmp.y]);
continue;
}
if (vis[tmp.x][tmp.y] + mp[tx][ty] < vis[tx][ty]) {
que.push(nodes(tx, ty));
vis[tx][ty] = vis[tmp.x][tmp.y] + mp[tx][ty];
}
}
}
}
int main() {
while (~scanf("%d", &n)) {
for (int i = 0; i < n; i++) {
for (int j = 0; j < n; j++) {
scanf("%d", &mp[i][j]);
if (mp[i][j] == -1) st = nodes(i, j);
else if (mp[i][j] == -2) en = nodes(i, j);
}
}
bfs();
printf("%d\n", vis[en.x][en.y]);
}
return 0;
}
需要精度高的pi,读者可以直接复制高高精度的pi,或者用acos(-1)表示(笔者推荐后者)
因为要由变量确定精度,所以用c++的iomanip头文件中的输出修正
#include<iostream>
#include<string>
#include<cstring>
#include<vector>
#include<map>
#include<algorithm>
#include<queue>
#include<set>
#include<cstdio>
#include<functional>
#include<iomanip>
#include<cmath>
#include<stack>
#include<iomanip>
#include<functional>
#include <iomanip>
using namespace std;
typedef long long LL;
typedef unsigned long long ull;
const int maxn = (int)1e5 + 10;
const int BN = 30;
const int inf = 0x3f3f3f3f;
const LL INF = 0x3f3f3f3f3f3f3f3f;
const int mod = 1000000007;
const double eps = 1e-6;
const double r = 6371009;
const double PI = acos(-1);
int main() {
int t;
scanf("%d", &t);
while (t--) {
int a, b;
scanf("%d%d", &a, &b);
double ans = pow(a, PI);
cout << fixed << setprecision(b) << ans << endl;;
}
return 0;
}
这里的颜料混合和盐水稀释是一个道理的,所以除了要考虑浓度之外还要注意混合是体积也会有影响。
根据盐水稀释,如果把浓度和体积设为横坐标和纵坐标,两倍盐水能稀释的范围在两点连线上的点。
以此类推,三个点的话能稀释的范围就是在三角形内。
问题转换为点是否在三角形内。
读者可以直接用几何模板,这里笔者提供一种三角形的思路。
如果点在三角形内,那么点把三角形分割成三个三角形,这三个三角形的面积和和原来的一定相等。
#include<iostream>
#include<string>
#include<cstring>
#include<vector>
#include<map>
#include<algorithm>
#include<queue>
#include<set>
#include<cstdio>
#include<functional>
#include<iomanip>
#include<cmath>
#include<stack>
#include<iomanip>
#include<functional>
#include <iomanip>
using namespace std;
typedef long long LL;
typedef unsigned long long ull;
const int maxn = (int)1e5 + 10;
const int BN = 30;
const int inf = 0x3f3f3f3f;
const LL INF = 0x3f3f3f3f3f3f3f3f;
const int mod = 1000000007;
const double eps = 1e-6;
const double r = 6371009;
const double PI = acos(-1);
int area(int x1, int y1, int x2, int y2) { return abs(x1 * y2 - x2 * y1); }
int main() {
int x0, y0, x1, y1, x2, y2, x3, y3;
while (cin >> x0 >> y0 >> x1 >> y1 >> x2 >> y2 >> x3 >> y3) {
int tri = area(x2 - x1, y2 - y1, x3 - x1, y3 - y1);
int s1 = area(x1 - x0, y1 - y0, x2 - x0, y2 - y0);
int s2 = area(x2 - x0, y2 - y0, x3 - x0, y3 - y0);
int s3 = area(x1 - x0, y1 - y0, x3 - x0, y3 - y0);
if (s1 + s2 + s3 == tri)
cout << "Yes" << endl;
else
cout << "No" << endl;
}
return 0;
}
直接模拟就行了
#include<iostream>
#include<string>
#include<cstring>
#include<vector>
#include<map>
#include<algorithm>
#include<queue>
#include<set>
#include<cstdio>
#include<functional>
#include<iomanip>
#include<cmath>
#include<stack>
#include<iomanip>
#include<functional>
#include <iomanip>
using namespace std;
typedef long long LL;
typedef unsigned long long ull;
const int maxn = (int)1e5 + 10;
const int BN = 30;
const int inf = 0x3f3f3f3f;
const LL INF = 0x3f3f3f3f3f3f3f3f;
const int mod = 1000000007;
const double eps = 1e-6;
const double r = 6371009;
const double PI = acos(-1);
int num[111];
int main() {
int n;
while (~scanf("%d", &n)) {
int a[4];
a[1] = 1, a[2] = 2, a[3] = 3;
for (int i = 0; i < n; i++)
scanf("%d", &num[i]);
bool flag = true;
for (int i = 0; i < n; i++) {
if (a[1] == num[i] || a[2] == num[i]) {
if (a[1] == num[i]) swap(a[2], a[3]);
else swap(a[1], a[3]);
}
else {
flag = false;
break;
}
}
printf("%s\n", flag ? "YES" : "NO");
}
return 0;
}
大数乘法随便来
#!/usr/bin/env python3
# -*- coding: utf-8 -*-
t=int(input())
for x in range(t):
a,b=input().split( )
a=int(a)
b=int(b)
a=a*b
print(a)
因为如果没有扫到雷要求输出矩阵,所以要设一个数组保留最后答案。
扫到的点分三种
1:扫到雷,直接返回失败。
2:扫到数字,把这个数字赋值给答案数组。
3:扫到.,把剩余的八联通块进行bfs。
#include<iostream>
#include<string>
#include<cstring>
#include<vector>
#include<map>
#include<algorithm>
#include<queue>
#include<set>
#include<cstdio>
#include<functional>
#include<iomanip>
#include<cmath>
#include<stack>
#include<iomanip>
#include<functional>
#include <iomanip>
using namespace std;
typedef long long LL;
typedef unsigned long long ull;
const int maxn = (int)1e5 + 10;
const int BN = 30;
const int inf = 0x3f3f3f3f;
const LL INF = 0x3f3f3f3f3f3f3f3f;
const int mod = 1000000007;
const double eps = 1e-6;
const double r = 6371009;
const double PI = acos(-1);
struct nodes {
int x, y;
nodes(int a = 0, int b = 0) :x(a), y(b) {}
}ser[15];
int n, m;
char ansmp[555][555], mp[555][555];
int dx[] = { 0,0,1,-1,-1,-1,1,1 }, dy[] = { 1,-1,0,0,-1,1,-1,1 };
bool vis[555][555];
bool check(int x, int y) {
if (x < 0 || x >= n || y < 0 || y >= m) return true;
else if (vis[x][y]) return true;
return false;
}
bool bfs(int x, int y) {
if (mp[x][y] == '*') return true;
else if (mp[x][y] >= '1'&&mp[x][y] <= '8') {
vis[x][y] = true;
ansmp[x][y] = mp[x][y];
return false;
}
else {
queue<nodes>que;
que.push(nodes(x, y));
ansmp[x][y] = '0';
while (!que.empty()) {
nodes tmp = que.front();
que.pop();
int nx = tmp.x, ny = tmp.y;
for (int i = 0; i < 8; i++) {
int tx = nx + dx[i], ty = ny + dy[i];
if (check(tx, ty)) continue;
vis[tx][ty] = true;
if (mp[tx][ty] >= '1'&&mp[tx][ty] <= '8')
ansmp[tx][ty] = mp[tx][ty];
else {
ansmp[tx][ty] = '0';
que.push(nodes(tx, ty));
}
}
}
return false;
}
}
int main() {
int t;
scanf("%d", &t);
while (t--) {
int q;
scanf("%d%d%d", &n, &m, &q);
for (int i = 0; i < n; i++) {
scanf("%s", mp[i]);
for (int j = 0; j < m; j++) {
ansmp[i][j] = '.';
vis[i][j] = 0;
}
}
bool flag = true;
int ans = 0;
for (int i = 0; i < q; i++)
scanf("%d%d", &ser[i].x, &ser[i].y);
for (int i = 0; i < q; i++) {
if (bfs(ser[i].x - 1, ser[i].y - 1)) {
flag = false;
ans = i + 1;
break;
}
}
if (!flag) printf("Game over in step %d\n", ans);
else {
for (int i = 0; i < n; i++)
printf("%s\n", ansmp[i]);
}
}
return 0;
}
签到题
#include<iostream>
#include<string>
#include<cstring>
#include<vector>
#include<map>
#include<algorithm>
#include<queue>
#include<set>
#include<cstdio>
#include<functional>
#include<iomanip>
#include<cmath>
#include<stack>
#include<iomanip>
#include<functional>
#include <iomanip>
using namespace std;
typedef long long LL;
typedef unsigned long long ull;
const int maxn = (int)1e5 + 10;
const int BN = 30;
const int inf = 0x3f3f3f3f;
const LL INF = 0x3f3f3f3f3f3f3f3f;
const int mod = 1000000007;
const double eps = 1e-6;
const double r = 6371009;
const double PI = acos(-1);
char str[1111][10];
int main() {
int n;
while (~scanf("%d", &n)) {
bool flag = false;
for (int i = 0; i < n; i++) {
scanf("%s", str[i]);
if (flag)continue;
if (str[i][0] == 'O'&&str[i][1] == 'O') {
flag = true;
str[i][0] = str[i][1] = '+';
}
else if (str[i][3] == 'O'&&str[i][4] == 'O') {
flag = true;
str[i][3] = str[i][4] = '+';
}
}
if (!flag) printf("NO\n");
else {
printf("YES\n");
for (int i = 0; i < n; i++)
printf("%s\n", str[i]);
}
}
return 0;
}
实际为一个非严格递增的lis
#include<iostream>
#include<string>
#include<cstring>
#include<vector>
#include<map>
#include<algorithm>
#include<queue>
#include<set>
#include<cstdio>
#include<functional>
#include<iomanip>
#include<cmath>
#include<stack>
#include<iomanip>
#include<functional>
#include <iomanip>
using namespace std;
typedef long long LL;
typedef unsigned long long ull;
const int maxn = (int)1e5 + 10;
const int BN = 30;
const int inf = 0x3f3f3f3f;
const LL INF = 0x3f3f3f3f3f3f3f3f;
const int mod = 1000000007;
const double eps = 1e-6;
const double r = 6371009;
const double PI = acos(-1);
int dp[111], num[111];
int lis(int l) {
dp[1] = num[1];
int len = 1;
for (int i = 2; i <= l; ++i) {
if (num[i] >= dp[len])
dp[++len] = num[i];
else {
int pos = upper_bound(dp + 1, dp + len + 1, num[i]) - dp;
dp[pos] = num[i];
}
}
return len;
}
int main() {
int n;
while (~scanf("%d", &n)) {
memset(dp, 0, sizeof(dp));
for (int i = 1; i <= n; i++)
scanf("%d", &num[i]);
printf("%d\n", lis(n));
}
return 0;
}
数学题。非常要命
首先要说一些题目问题。
车和人是同时从起点出发的。题目要求输出的是最短时间,也就是最优解。车是可以随时放人下车和掉头的。
那么先说结论,为了让车被使用的效率最高,除了最后一批人是坐车直接到目的地之外。
每一批人都是 走路一段-》上车-》车走一段-》下车走-》终点的流程。并且人都是同时到达的(包括最后一批坐车的)
车就是在不断来回接人。
之所以不直接载到终点是为了尽量多用车代步使用时减少。
那么问题来了车在哪里放人下车最优。
首先先说几个结论,1:每一批人走的距离是一样的。2:车载每一批人行驶的距离也是一样的(理由是因为要同时到达)
设一共有p批人
对于第一批人,起点为0的位置,如果他们是在x位置下车的,那么车回头和向前走的人相遇地点在2*v1*x/(v1+v2) (这里读者自己证明),设其为y。
对于第二批人起点在y,根据上面的公式可知车会在2*y的位置和向前走的人相遇。
......
第p批的时候起点在(p-1)*y,因为他们是直接坐车到终点的,坐车距离是x
那么有关系式 L-(p-1)*y=x
化简得x=l*(v1 + v2) / (2.0*v1*(p - 1) + v1 + v2)
结果就为x/v2+(l-x)/v1
(数学题惹不起)
#include<iostream>
#include<string>
#include<cstring>
#include<vector>
#include<map>
#include<algorithm>
#include<queue>
#include<set>
#include<cstdio>
#include<functional>
#include<iomanip>
#include<cmath>
#include<stack>
#include<iomanip>
#include<functional>
#include <iomanip>
using namespace std;
typedef long long LL;
typedef unsigned long long ull;
const int maxn = (int)1e5 + 10;
const int BN = 30;
const int inf = 0x3f3f3f3f;
const LL INF = 0x3f3f3f3f3f3f3f3f;
const int mod = 1000000007;
const double eps = 1e-6;
const double r = 6371009;
const double PI = acos(-1);
int main() {
int n, k, m;
double l, v1, v2;
scanf("%d", &m);
while (m--) {
scanf("%d%lf%lf%lf%d", &n, &l, &v1, &v2, &k);
int p = n / k + (n%k == 0 ? 0 : 1);
double x = l*(v1 + v2) / (2.0*v1*(p - 1) + v1 + v2);
printf("%.10lf\n", x / v2 + (l - x) / v1);
}
return 0;
}
物理题。
首先要确定一点的是题目要求的是船头一直指向正对岸,这是船是走曲线的。
建立坐标系,设船到起点的坐标为r,水平位移为x
那么有
对两者求积分可得
解得
然后因为这是一道原题,读者觉得不清楚可以百度。
题号hdu 5761
#include<iostream>
#include<string>
#include<cstring>
#include<vector>
#include<map>
#include<algorithm>
#include<queue>
#include<set>
#include<cstdio>
#include<functional>
#include<iomanip>
#include<cmath>
#include<stack>
#include<iomanip>
#include<functional>
#include <iomanip>
using namespace std;
typedef long long LL;
typedef unsigned long long ull;
const int maxn = (int)1e5 + 10;
const int BN = 30;
const int inf = 0x3f3f3f3f;
const LL INF = 0x3f3f3f3f3f3f3f3f;
const int mod = 1000000007;
const double eps = 1e-6;
const double r = 6371009;
const double PI = acos(-1);
int a, v1, v2;
int main() {
int t;
scanf("%d", &t);
while (t--) {
scanf("%d%d%d", &a, &v1, &v2);
if (a == 0)
printf("0.0000000000\n");
else if (v1 <= v2)
printf("Infinity\n");
else
printf("%.10f\n", 1.0*a*v1 / (v1*v1 - v2*v2));
}
return 0;
}