A:
题意:
给两个串t,p,像密码锁那样每次滑动一个,问最短滑动多少次。
代码:
#include <iostream>
#include <cstdio>
#include <cstdlib>
#include <algorithm>
#include <cstring>
#include <cmath>
#include <stack>
#include <vector>
#include <queue>
#include <map>
#include <climits>
#include <cassert>
#define LL long long
#define lson lo, mi, rt << 1
#define rson mi + 1, hi, rt << 1 | 1
using namespace std;
const int maxn = 1000 + 10;
const int inf = 0x3f3f3f3f;
const double eps = 1e-8;
const double pi = acos(-1.0);
const double ee = exp(1.0);
char p[maxn];
char t[maxn];
int main()
{
#ifdef LOCAL
freopen("in.txt", "r", stdin);
#endif // LOCAL
int n;
scanf("%d", &n);
scanf("%s%s", p, t);
int ans = 0;
for (int i = 0; i < n; i++)
{
int pp = p[i] - '0';
int tt = t[i] - '0';
ans += min(abs(pp - tt), 10 - abs(pp - tt));
}
cout << ans << endl;
return 0;
}
B:
题意:
天才小明有n门考试,已经考了k门,每一门的考试分数范围是1~p,他太厉害了可以控制自己考试分数考在范围内的任意分数上。
小明为了不让自己太装逼,所以他想让自己的分数的和小于等于x,但是为了让他妈继续给他打游戏,他成绩的中位数又不能低于y。
现在给你已经考了k门的课程的成绩,让你计算余下满足要求的n - k门考试他应该考多少分。
解析:
这题数据太神了。
首先先确定,为了让分数小于等于x,中位数不低于y,考的任意分数就可以确定了,最低用1,最高用y,这样处理就可以让两个条件满足并且简化。
然后为了使中位数落在y之上,最后分数集合中大于等于y的数应该大于小于等于y的数的。
所以用余下的分数总和除以y来计算最多可以放入多少个y,然后协调左右,计算出结果。
注意的是,给的数据中,有可能可以放入的y的个数远远大于余下课程数量,所以要加个取小的数的判断。,。
并且,在确定了之后,还要调整大于y的个数和小于y的个数。
代码:
#include <iostream>
#include <cstdio>
#include <cstdlib>
#include <algorithm>
#include <cstring>
#include <cmath>
#include <stack>
#include <vector>
#include <queue>
#include <map>
#include <climits>
#include <cassert>
#define LL long long
#define lson lo, mi, rt << 1
#define rson mi + 1, hi, rt << 1 | 1
using namespace std;
const int maxn = 1000 + 10;
const int inf = 0x3f3f3f3f;
const double eps = 1e-8;
const double pi = acos(-1.0);
const double ee = exp(1.0);
int main()
{
#ifdef LOCAL
freopen("in.txt", "r", stdin);
#endif // LOCAL
int n, k, p, x, y;
scanf("%d%d%d%d%d", &n, &k, &p, &x, &y);
int sumMark = 0;
int greaterThan = 0;
int lessThan = 0;
for (int i = 0; i < k; i++)
{
int t;
scanf("%d", &t);
sumMark += t;
if (y <= t)
{
greaterThan++;
}
else
{
lessThan++;
}
}
int remainNum = n - k;
int remainSum = x - sumMark;
// cout << remainNum << " " << remainSum << endl;
// cout << greaterThan << " " << lessThan << endl;
int cntGT = remainSum / y;
int cntLT = remainNum - cntGT;
// cout << cntGT << " " << cntLT << endl;
cntGT = min(cntGT, remainNum);
cntLT = remainNum - cntGT;
while (cntGT * y + 1 * cntLT > remainSum && cntGT != -1)
{
cntGT--;
cntLT++;
}
if (cntGT == -1)
{
printf("-1\n");
}
else
{
// cout << cntGT << " " << cntLT << endl;
if (cntGT + greaterThan < cntLT + lessThan)
{
printf("-1\n");
}
else
{
// cout << cntGT << " " << cntLT << endl;
for (int i = 0; i < cntGT; i++)
{
printf("%d ", y);
}
for (int i = 0; i < cntLT; i++)
{
printf("1 ");
}
}
}
return 0;
}
C:
题意:
给一个n * m的冰面。
“ . ” 代表这个冰面还没有被踩过;“ X ”表示这个冰面已经被踩过了,再次踩这个冰面的时候就会掉下去。
现在小明从 sx,sy出发,问他能否从 ex, ey,这个点掉到冰面下去。
解析:
开始弱智了,想先找到ex,ey然后去找某条路径能回到ex,ey。
然后LGG提醒,找到ex,ey之后,若ex,ey是“X”,那就直接YES了;
如果不是,只要判断终点周围存不存在“ . ", 如果存在,肯定能回到ex,ey并且掉下去。
所以先用bfs() , O(n)找到终点,并且标记上每一点的step。
找到终点后,判断周围有”."并且未被step标记或者周围有”.",标记的step大于终点的step,或者周围有”."并且有两个相等的step,即YES,否则NO。
代码:
#include <iostream>
#include <cstdio>
#include <cstdlib>
#include <algorithm>
#include <cstring>
#include <cmath>
#include <stack>
#include <vector>
#include <queue>
#include <map>
#include <climits>
#include <cassert>
#define LL long long
#define lson lo, mi, rt << 1
#define rson mi + 1, hi, rt << 1 | 1
using namespace std;
const int maxn = 500 + 10;
const int inf = 0x3f3f3f3f;
const double eps = 1e-8;
const double pi = acos(-1.0);
const double ee = exp(1.0);
int dir[][2] = {{1, 0}, {-1, 0}, {0, 1}, {0, -1}};
int n, m;
char g[maxn][maxn];
int sx, sy, ex, ey;
int step[maxn][maxn];
struct Node
{
int x, y;
Node(int _x, int _y)
{
x = _x;
y = _y;
}
};
bool isOk(int x, int y)
{
int ans[4];
int cnt = 0;
for (int i = 0; i < 4; i++)
{
int nx = x + dir[i][0];
int ny = y + dir[i][1];
if (0 <= nx && nx < n && 0 <= ny && ny < m)
{
if ((step[nx][ny] == -1 && g[nx][ny] == '.') || step[x][y] < step[nx][ny])
return true;
else if (step[nx][ny] != -1)
ans[cnt++] = step[nx][ny];
}
}
// cout << cnt << endl;
sort(ans, ans + cnt);
// for (int i = 0; i < cnt; i++)
// cout <<ans[i]<< endl;
for (int i = 1; i < cnt; i++)
if (ans[i - 1] == ans[i])
return true;
return false;
}
bool bfsFindWay()
{
memset(step, -1, sizeof(step));
queue<Node> q;
step[sx][sy] = 0;
q.push(Node(sx, sy));
while (!q.empty())
{
Node now = q.front();
q.pop();
int x = now.x;
int y = now.y;
if (x == ex && y == ey)
{
return isOk(ex, ey);
}
for (int i = 0; i < 4; i++)
{
int nx = x + dir[i][0];
int ny = y + dir[i][1];
if (0 <= nx && nx < n && 0 <= ny && ny < m)
{
if (nx == ex && ny == ey && g[nx][ny] == 'X')
return true;
if (g[nx][ny] != 'X')
{
if (step[nx][ny] == -1)
{
step[nx][ny] = step[x][y] + 1;
q.push(Node(nx, ny));
}
}
}
}
}
return false;
}
int main()
{
#ifdef LOCAL
freopen("in.txt", "r", stdin);
#endif // LOCAL
scanf("%d%d", &n, &m);
for (int i = 0; i < n; i++)
{
scanf("%s", g[i]);
}
scanf("%d%d%d%d", &sx, &sy, &ex, &ey);
sx--, sy--, ex--, ey--;
if (bfsFindWay())
{
printf("YES\n");
}
else
{
printf("NO\n");
}
// for (int i = 0; i < n; i++)
// {
// for (int j = 0; j < m; j++)
// {
// printf("%5d ", step[i][j]);
// }
// printf("\n");
// }
return 0;
}
D:
题意:
有三种生物生活在一个海岛上,锤子,剪刀,布,他们之间锤子可以吃剪刀,剪刀吃布,布吃锤子,每种生物相遇的概率是一样的。
现在给出三种生物的初始数量,计算经过足够长的时间以后,只剩下锤子的概率R,只剩下剪刀的概率S,只剩下布的概率P。。
解析:
设当前有锤子r只,剪刀s只,布p只,则锤子吃了剪刀的概率是: r * s / (r * s + r * p + s * p)。
所以 dp[ i ] [ j ] [ k ] 表示海岛上只剩下i只锤子,j只剪刀,k只布的时候的概率。
若布吃了锤子:
if (j != 0 || k != 0)
dp[i][j][k] += ((i + 1.0) * k / ((i + 1) * j + (i + 1) * k + j * k)) * dp[i + 1][j][k];
若锤子吃了剪刀:
if (i != 0 || k != 0)
dp[i][j][k] += ((j + 1.0) * i / (i * (j + 1) + i * k + (j + 1) * k)) * dp[i][j + 1][k];
若剪刀吃了布:
if (i != 0 || j != 0)
dp[i][j][k] += ((k + 1.0) * j / (i * j + i * (k + 1) + j * (k + 1))) * dp[i][j][k + 1];
初始状态下:
dp[ r ] [ s ] [ p ] = 1
代码:
#include <iostream>
#include <cstdio>
#include <cstdlib>
#include <algorithm>
#include <cstring>
#include <cmath>
#include <stack>
#include <vector>
#include <queue>
#include <map>
#include <climits>
#include <cassert>
#define LL long long
#define lson lo, mi, rt << 1
#define rson mi + 1, hi, rt << 1 | 1
using namespace std;
const int maxn = 100 + 10;
const int inf = 0x3f3f3f3f;
const double eps = 1e-8;
const double pi = acos(-1.0);
const double ee = exp(1.0);
double dp[maxn][maxn][maxn];
int main()
{
#ifdef LOCAL
freopen("in.txt", "r", stdin);
#endif // LOCAL
int r, s, p;
scanf("%d%d%d", &r, &s, &p);
memset(dp, 0, sizeof(dp));
dp[r][s][p] = 1.0;
for (int i = r; i >= 0; i--)
{
for (int j = s; j >= 0; j--)
{
for (int k = p; k >= 0; k--)
{
///all die, all live
if ((i == 0 && j == 0 && k == 0) || (i == r && j == s && k == p))
continue;
///k ate a i
if (j != 0 || k != 0)
dp[i][j][k] += ((i + 1.0) * k / ((i + 1) * j + (i + 1) * k + j * k)) * dp[i + 1][j][k];
///i ate a j
if (i != 0 || k != 0)
dp[i][j][k] += ((j + 1.0) * i / (i * (j + 1) + i * k + (j + 1) * k)) * dp[i][j + 1][k];
///j ate a k
if (i != 0 || j != 0)
dp[i][j][k] += ((k + 1.0) * j / (i * j + i * (k + 1) + j * (k + 1))) * dp[i][j][k + 1];
}
}
}
double R = 0, S = 0, P = 0;
for (int i = 1; i <= r; i++)
R += dp[i][0][0];
for (int i = 1; i <= s; i++)
S += dp[0][i][0];
for (int i = 1; i <= p; i++)
P += dp[0][0][i];
printf("%.12lf %.12lf %.12lf\n", R, S, P);
return 0;
}