您的位置:首页 > 其它

2013暑假集训B组训练赛第二场

2013-07-27 11:16 302 查看
Problem ACodeForces 79ABus Game 

这题先预处理求出三种拿钱方式(0、1、2张100),然后由这三种方式两两组合成9种方式;

然后按照优先选择的规则定义一个小于号,排一下序就ok了。

之后就是逐一的按照排好的顺序取钱。
#include <stdio.h>
#include <algorithm>
using namespace std;
struct Meth{
int hud, ten;
void init(int hud, int ten){
this->hud = hud, this->ten = ten;
}
bool operator==(const class Meth &ans)const{
return hud==ans.hud&&ten==ans.ten;
}
};
//两种比较方式
bool cmpC(const struct Meth &ans1, const struct Meth &ans2){
return ans1.hud>ans2.hud;
}
bool cmpH(const struct Meth &ans1, const struct Meth &ans2){
return ans1.ten>ans2.ten;
}
struct Comb{
Meth ci, ha;
int chud, cten;
void init(Meth a, Meth b){
ci.init(a.hud, a.ten), ha.init(b.hud, b.ten);
chud = ci.hud+ha.hud, cten = ci.ten+ha.ten;
}
bool operator<(const class Comb &ans)const{//按照规则定义小于号
return (cmpC(ci, ans.ci)||(ci==ans.ci&&cmpH(ha, ans.ha)));
}
};
Meth mat[3];
Comb comb[9];//综合的使用方式
int cnt, cnthud, cntten;
void Prepare(){
for(int i = 0; i < 3; i++)
mat[i].init(i, 22-i*10);
cnt = 0;
for(int i = 0; i < 3; i++)
for(int j = 0; j < 3; j++)
comb[cnt++].init(mat[i], mat[j]);
sort(comb, comb+cnt);
}
int main(){
Prepare();
while(scanf("%d%d", &cnthud, &cntten) != EOF){
for(int i = 0; i < cnt; i++){
if(cnthud >= comb[i].chud && cntten >= comb[i].cten){
int a = cntten/comb[i].cten;
//可能会使用0张100(comb[i].chud=0)
if(comb[i].chud != 0)    a = min(a, cnthud/comb[i].chud);
cnthud -= a*comb[i].chud, cntten -= a*comb[i].cten;
}
}
if(cnthud*100+cntten*10>=220 && cntten >= 2){
printf("Ciel\n");
}else{
printf("Hanako\n");
}
}
return 0;
}


Problem BCodeForces 192AFunky Numbers 
水题,先求出所有的10^9以内的k(k+1)/2的数,排序。

然后每个询问,枚举第一个k(k+1)/2的数,然后二分查找是否存在匹配的一个数,也就是看预处理的数组里是否存在n-(k+(k+1)/2)这个数。

#include <stdio.h>
#include <string.h>
#include <algorithm>
using namespace std;
typedef long long LL;
int cnt, n;
LL num[45000];
LL up = 1000000000;
void prepare(){
cnt = 0;
for(LL i = 1; ;i++){
LL tmp = i*(i+1)/2;
if(tmp <= up) num[cnt++] = tmp;
else break;
}
}
int main(){
prepare();
while(scanf("%d", &n) != EOF){
bool flag = false;
for(int i = 0; num[i] < n; i++){
int id = lower_bound(num, num+cnt, n-num[i])-num;//查找一个和num[i]互补的那种数
if(num[id]==n-num[i]){
flag = true;
break;
}
}
printf("%s\n", flag ? "YES" : "NO");
}
return 0;
}

Problem CCodeForces 329APurification 
首先检查是否可行,不可行的条件就是同时有一整行都不能放并且有一整列不能放。(十字架的形状)
若可行,肯定是是下面两种情况:

1.每一行都有一列可以放,放在每一行的这个列

2.每一列都有一行可以放,放在每一列的这个行

#include <stdio.h>
#include <string.h>
const int maxn = 100+10;
char str[maxn];
int row[maxn], col[maxn], n, m;
int main(){
while(scanf("%d%d", &n, &m) != EOF){
for(int i = 1; i <= n; i++){
memset(row, -1, sizeof(row));//该行全部都不能放
memset(col, -1, sizeof(col));
}
for(int i = 1; i <= n ; i++){
scanf("%s", &str[1]);
for(int j = 1; str[j]; j++){
if(str[j] == '.'){
row[i] = j, col[j] = i;//该行的j列放,该列的i行可放
}
}
}
int failr = -1, failc = -1;
for(int i = 1; i <= n; i++){
if(row[i]==-1)failr = i;
if(col[i]==-1)failc = i;
}
if(failr!=-1&&failc!=-1){
printf("-1\n");
continue;
}
if(failr==-1){//每行都有一个列可放
for(int i = 1; i <= n; i++)
printf("%d %d\n", i, row[i]);
}else{//每列都有个行可放
for(int j = 1; j <= n; j++)
printf("%d %d\n",  col[j], j);
}
}
return 0;
}


Problem DCodeForces 216BForming Teams 
由于每个人最多只有两个矛盾的人,所有这些人的仇恨关系不是一条链就是一个环(这些链和环不会和其他的链或环有关)

于是如果我们把有矛盾的人都归为一个集合,关键就成了查找数量为奇数的环的个数了

利用并查集,只要两个人有矛盾关系就把他们归为一个集合。

当出现一个矛盾关系,如果这两个人之前就有矛盾则说明出现了环,判断若为奇数,肯定有一个人要坐板凳了。

#include <stdio.h>
#include <vector>
using namespace std;
const int maxn = 100+10;
int n, m, ans;
int fa[maxn], num[maxn];//集合的数量
int Root(int cur){
if(fa[cur] != cur)
fa[cur] = Root(fa[cur]);
return fa[cur];
}
int main(){
while(scanf("%d%d", &n, &m) != EOF){
for(int i = 1; i <= n; i++)
fa[i] = i, num[i] = 1;
int a, b;
ans = 0;
for(int i = 1; i <= m; i++){
scanf("%d%d", &a, &b);
int r1 = Root(a), r2 = Root(b);
if(r1 == r2 && (num[r1]%2==1))//ÕÒµ½Ææ»·
ans++;
else
fa[r1] = r2, num[r2] += num[r1];
}
if((n-ans)%2==1)
ans++;
printf("%d\n", ans);
}
return 0;
}

Problem ECodeForces 266BQueue at the School 
这种题就是照着题目做,一步一步来就可以了
#include <stdio.h>
#include <string.h>
const int maxn = 60;
char str[2][maxn];
bool flag[maxn];
int n, t, now, pre;
int main(){
while(scanf("%d%d", &n, &t) != EOF){
now = 0, pre = 1;
scanf("%s", str[now]);
for(int i = 0; i < t; i++){
now ^= 1, pre ^= 1;
memset(flag, false, sizeof(flag));//要不要改
for(int j = 0; j < n-1; j++){
if(str[pre][j]=='B' && str[pre][j+1]=='G')//前面是男的后面是女的
flag[j] = flag[j+1] = true;//要改
}
for(int j = 0; j < n; j++)
if(flag[j])
str[now][j]=(str[pre][j]=='G' ? 'B' : 'G');
else
str[now][j]=str[pre][j];
}
str[now]
=0;
printf("%s\n", str[now]);
}
return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: