Codeforces Round #301 (Div. 2) -- (A,B,C,D)

题目传送:Codeforces Round #301 (Div. 2)

A. Combination Lock

水题,求最小移动次数,简单贪心一下即可

AC代码:

#include <cstdio>
#include <cstring>
#include <iostream>
#include <algorithm>
#include <cmath>
#include <queue>
#include <stack>
#include <vector>
#include <map>
#include <set>
#include <deque>
#include <cctype>
#define LL long long
#define INF 0x7fffffff
using namespace std;

int n; 

char s1[1005];
char s2[1005];

int main() {
	scanf("%d", &n);
	scanf("%s %s", s1, s2);
	int ans = 0;
	for(int i = 0; i < n; i ++) {
		if(s2[i] > s1[i]) {
			ans += min(s2[i] - s1[i], s1[i] + 10 - s2[i]);
		}
		else {
			ans += min(s1[i] - s2[i], s2[i] + 10 - s1[i]);
		}
	}
	printf("%d\n", ans);
	return 0;
}

B. School Marks

也比较简单,就是有点繁琐,具体看代码吧

AC代码:

#include <cstdio>
#include <cstring>
#include <iostream>
#include <algorithm>
#include <cmath>
#include <queue>
#include <stack>
#include <vector>
#include <map>
#include <set>
#include <deque>
#include <cctype>
#define LL long long
#define INF 0x7fffffff
using namespace std;

int n, k, p, x, y;

int a[1005];

int main() {
	scanf("%d %d %d %d %d", &n, &k, &p, &x, &y);
	int tot = 0;//记录当前的总和
	int cnt = 0;//记录当前大于y的数目
	for(int i = 0; i < k; i ++) {
		scanf("%d", &a[i]);
		tot += a[i];
		if(a[i] >= y) {
			cnt ++;
		}
	}
	int mid = (n + 1) / 2;
	int xu;//记录最少所需要的数
	if(k - cnt >= mid) {//当前如果有半数都比y小则输出-1
		printf("-1\n");
		return 0;
	}
	if(cnt < mid) {//比y大的少于mid的情况
		xu = (mid - cnt) * y;
		xu += (n - k - (mid - cnt));
		if(xu <= x - tot) {
			for(int i = 0; i < n - k - (mid - cnt); i ++) {
				printf("1 ");
			}
			for(int i = 0; i < mid - cnt; i ++) {
				printf("%d ", y);
			}
		}
		else {
			printf("-1\n");
		}
	}
	else {		//比y大的大于等于mid的情况
		xu = n - k;
		if(xu <= x - tot) {
			for(int i = 0; i < n - k; i ++) {
				printf("1 ");
			}
		}
		else printf("-1\n");
	}
	return 0;
}

C. Ice Cave

题意:很简单,就是一个n*m的冰面,有的破碎了,走一次就会陷下去,有的完好的,不过走一次就破碎了,下次走就会陷下去,给你一个起点和终点,看起点能否走到终点那里陷下去,注意起点肯定是破碎的,且终点可能会和起点相同

思路:首先,特判一下起点和终点相同的情况,然后bfs一下看起点能否能走到终点,然后根据终点的情况分类,当终点为破碎的冰时,只要找到路径即YES,否则NO,当终点为完好的冰时,到了终点后还要走出去再回来,这里注意,只要当前挨着的冰有一块为‘.‘(即完好的),则成立,输出YES,否则输出NO;只需要预处理一下原来终点挨着的冰块的‘.‘的个数cnt即可(cnt>=2就YES,否则NO),然后这里需要特判一下起点和终点挨着的情况(因为此时只需要cnt>=1即可,这里尤其猥琐)

AC代码:

#include <cstdio>
#include <cstring>
#include <iostream>
#include <algorithm>
#include <cmath>
#include <queue>
#include <stack>
#include <vector>
#include <map>
#include <set>
#include <deque>
#include <cctype>
#define LL long long
#define INF 0x7fffffff
using namespace std;

struct node {
	int x, y;
	node(int x,int y) : x(x), y(y) {}
};

int n, m;
int mp[505][505];

int mx[4] = {-1, 0, 1, 0};
int my[4] = {0, 1, 0, -1};

int r1, c1;
int r2, c2;

char s[505];

int bfs() {		//bfs找路径
	queue<node> que;
	mp[r1][c1] --;
	que.push(node(r1, c1));
	while(!que.empty()) {
		node tmp = que.front();
		que.pop();
		for(int i = 0; i < 4; i ++) {
			int xx = tmp.x + mx[i];
			int yy = tmp.y + my[i];
			if(xx >= 1 && xx <= n && yy <= m && yy >= 1) {
				if(xx == r2 && yy == c2) return 1;
				if(mp[xx][yy] == 2) {
					mp[xx][yy] --;
					que.push(node(xx, yy));
				}
			}
		}
	}
	return 0;
}

int main() {
	scanf("%d %d", &n, &m);
	for(int i = 0; i < n; i ++) {
		scanf("%s", s);
		int len = strlen(s);
		for(int j = 0; j < len; j ++) {
			if(s[j] == '.') {
				mp[i + 1][j + 1] = 2;
			}
			else {
				mp[i + 1][j + 1] = 1;
			}
		}
	}

	scanf("%d %d %d %d", &r1, &c1, &r2, &c2);

	int cnt = 0;//记录终点旁边有几个'.'
	for(int i = 0; i < 4; i ++) {
		int xx = r2 + mx[i];
		int yy = c2 + my[i];
		if(mp[xx][yy] == 2) cnt ++;
	}

	if(r1 == r2 && c1 == c2) {//特判一下起点和终点相同的情况
		if(cnt >= 1) {
			printf("YES\n");
		}
		else printf("NO\n");
		return 0;
	}

	int flag = 0;//特判一下起点和终点相邻的情况,这里特别坑,感觉坑了好多人
	for(int i = 0; i < 4; i ++) {
		int xx = r1 + mx[i];
		int yy = c1 + my[i];
		if(xx == r2 && yy == c2) {
			flag = 1;
			break;
		}
	}
	if(flag) {
		if(mp[r2][c2] == 1) {
			printf("YES\n");
		}
		else {
			if(cnt >= 1) {
				printf("YES\n");
			}
			else printf("NO\n");
		}
		return 0;
	}
	//起点和终点不相同且不相邻的情况
	if(mp[r2][c2] == 1) {
		if(bfs()) {
			printf("YES\n");
		}
		else printf("NO\n");
	}
	else {
		if(bfs()) {
			if(cnt >= 2) {
				printf("YES\n");
			}
			else printf("NO\n");
		}
		else printf("NO\n");
	}

	return 0;
}

D. Bad Luck Island

思路:概率DP,设状态dp[i][j][k]为此时石头i个剪刀j个布k个的概率,可以知道dp[i][j][k]肯定由dp[i+1][j][k],dp[i][j+1][k],dp[i][j][k+1]得来,初始状态dp[r][s][p]为1,具体看代码

AC代码:

#include <cstdio>
#include <cstring>
#include <iostream>
#include <algorithm>
#include <cmath>
#include <queue>
#include <stack>
#include <vector>
#include <map>
#include <set>
#include <deque>
#include <cctype>
#define LL long long
#define INF 0x7fffffff
using namespace std;

int r, s, p;

double dp[105][105][105];

int main() {
	cin >> r >> s >> p;

	dp[r][s][p] = 1;

	for(int i = r; i >= 0; i --) {
		for(int j = s; j >= 0; j --) {
			for(int k = p; k >= 0; k --) {
				if(i == r && j == s && k == p) continue;

				double sum = i + j + k + 1; //上一状态的总数
				if(sum <= 1) continue;//全为0的时候就不需要计算了
				double t1 = 0, t2 = 0, t3 = 0;
				double t = 0;

				t1 = 2.0 * dp[i + 1][j][k] * (i + 1) / sum * k / (sum - 1);
				//当随机出现的是相同的人时的概率,这个概率不应该算到dp里面
				t = (i+1)/sum*i/(sum-1) + j/sum*(j-1)/(sum-1) + k/sum*(k-1)/(sum-1);
				if(t < 1.0) t1 /= (1.0 - t);//通过比例消掉 

				t2 = 2.0 * dp[i][j + 1][k] * (j + 1) / sum * i / (sum - 1);
				t = i/sum*(i-1)/(sum-1) + (j+1)/sum*j/(sum-1) + k/sum*(k-1)/(sum-1);
				if(t < 1.0) t2 /= (1.0 - t);

				t3 = 2.0 * dp[i][j][k + 1] * (k + 1) / sum * j / (sum - 1);
				t = i/sum*(i-1)/(sum-1) + j/sum*(j-1)/(sum-1) + (k+1)/sum*k/(sum-1);
				if(t < 1.0) t3 /= (1.0 - t);

				dp[i][j][k] = t1 + t2 + t3;//统计上一状态到当前状态的概率
			}
		}
	} 

	double ansr = 0;
	double anss = 0;
	double ansp = 0;

	for(int i = 1; i <= r; i ++) {
		ansr += dp[i][0][0];
	}
	for(int i = 1; i <= s; i ++) {
		anss += dp[0][i][0];
	}
	for(int i = 1; i <= p; i ++) {
		ansp += dp[0][0][i];
	}
	printf("%.12lf %.12lf %.12lf\n", ansr, anss, ansp);

	return 0;
}
时间: 2024-12-14 17:15:57

Codeforces Round #301 (Div. 2) -- (A,B,C,D)的相关文章

Codeforces Round #301 (Div. 2)(树状数组+离散化)

E. Infinite Inversions time limit per test 2 seconds memory limit per test 256 megabytes input standard input output standard output There is an infinite sequence consisting of all positive integers in the increasing order: p?=?{1,?2,?3,?...}. We per

Codeforces Round #259 (Div. 2) (简单模拟实现题)

题目链接:http://codeforces.com/problemset/problem/454/A A. Little Pony and Crystal Mine time limit per test 1 second memory limit per test 256 megabytes input standard input output standard output Twilight Sparkle once got a crystal from the Crystal Mine

Codeforces Round #561 (Div. 2) (还差2题)

总结:bitset的基本操作:http://www.cnblogs.com/RabbitHu/p/bitset.html B题中求每行每列均有...,只要在下一行中把上一行的第一个放到最后一个就能构造满足条件的解: C题中这种,如果直接讨论绝对值的情况有点多,直接自己写几个例子试试会快上很多: E题中用bitset处理这些集合是否重合特别的快,代码也很简洁: 题目链接:http://codeforces.com/contest/1166 A: 题意:自己看看,练练英语,英语太菜了 题解:签到就行

Codeforces Round #324 (Div. 2) (快速判断素数模板)

蛋疼的比赛,当天忘了做了,做的模拟,太久没怎么做题了,然后C题这么简单的思路却一直卡到死,期间看了下D然后随便猜了下,暴力了下就过了. A.找一个能被t整除的n位数,那么除了<=10以外,其他都可以用长度为n的10或100,1000 ... 来往上加几个数而得到 #include <iostream> #include <stdio.h> #include <set> #include <algorithm> #include <string.h

Codeforces Round #530 (Div. 2) (前三题题解)

总评 今天是个上分的好日子,可惜12:30修仙场并没有打... A. Snowball(小模拟) 我上来还以为直接能O(1)算出来没想到还能小于等于0的时候变成0,那么只能小模拟了.从最高的地方进行高度的模拟,如果遇到石头就去判断一下会不会小于0其他没有什么好说的了 代码 #include <bits/stdc++.h> using namespace std; int main() { ios::sync_with_stdio(0); cin.tie(0); cout.tie(0); int

Codeforces Round #559 (Div. 2) (还差2题)

总结:这次写的太菜了,一个B题写了很久, 这种维护一个最小值在计算的题目,下次要反应快点: C题是一个贪心,写的时候也是想了好久.... D题这个范围. A: 签到,算一个最开始有多少就行了,注意可以取到0,复杂度O(n) #include <cstdio> #include <iostream> using namespace std; int main() { int n; char c; int ca=0, cb=0, beg=0; cin>>n; while(n

Codeforces Round #259 (Div. 2) (序列)

题目链接:http://codeforces.com/contest/454/problem/B B. Little Pony and Sort by Shift time limit per test 1 second memory limit per test 256 megabytes input standard input output standard output One day, Twilight Sparkle is interested in how to sort a se

DFS/BFS Codeforces Round #301 (Div. 2) C. Ice Cave

题目传送门 1 /* 2 题意:告诉起点终点,踩一次, '.'变成'X',再踩一次,冰块破碎,问是否能使终点冰破碎 3 DFS:如题解所说,分三种情况:1. 如果两点重合,只要往外走一步再走回来就行了:2. 若两点相邻, 4 那么要不就是踩一脚就破了或者踩一脚走开再走回来踩一脚破了:3. 普通的搜索看是否能到达, 5 若能还是要讨论终点踩几脚的问题:) 6 DFS 耗时大,险些超时,可以用BFS来做 7 */ 8 #include <cstdio> 9 #include <algorit

贪心 Codeforces Round #301 (Div. 2) A. Combination Lock

题目传送门 1 /* 2 贪心水题:累加到目标数字的距离,两头找取最小值 3 */ 4 #include <cstdio> 5 #include <iostream> 6 #include <algorithm> 7 #include <cstring> 8 using namespace std; 9 10 const int MAXN = 1e3 + 10; 11 const int INF = 0x3f3f3f3f; 12 char s[MAXN],