Codeforces Round #601 (Div. 2)

A:Changing Volume

题意:你可以对一个数进行(−5,−2,−1,+1,+2,+5)六种操作任意次数,但在操作过程中给定的数不能变为负数,求最少操作几次可以将a变成b。

思路:简单讨论即可。

代码:

#include <iostream>
 
using namespace std;
 
int main()
{
	ios::sync_with_stdio(false);
	cin.tie(0), cout.tie(0);
	int n, a, b;
	cin>>n;
	while(n--){
		cin>>a>>b;
		int sum = 0;
		if(a == b){
			cout<<0<<'\n';
		}
		else if(a < b){
			sum = (b-a)/5;
			if((b-a)%5 == 3 || (b-a)%5 == 4)
				sum += 2;
			else if((b-a)%5 == 1 || (b-a)%5 == 2)
				sum += 1;
			cout<<sum<<'\n';
		}
		else{
			sum = (a-b)/5;
			if((a-b)%5 == 3 || (a-b)%5 == 4)
				sum += 2;
			else if((a-b)%5 == 1 || (a-b)%5 == 2)
				sum += 1;
			cout<<sum<<'\n';
		}
	}	
	return 0;
}

B:Fridge Lockers

题意:有m个冰箱,每个冰箱有一个值a,可以在两个冰箱之间加锁链,花费为a1+a2,每个冰箱有一个对应的主人,每个冰箱的主人知道自己冰箱所连的所有锁链的密码,当一个冰箱的所有锁链都被解开时冰箱打开,现在有n个冰箱,你需要建造m条锁链,问是否可以使得每个冰箱只能被自己的主人单独打开,其他人无法单独打开,如果是,那么输出最小花费以及每一条锁链连接的冰箱信息,否则输出-1。

思路:要想冰箱只能被自己的主人打开,那么每一台冰箱都至少连两台不同的冰箱,最优的情况就是连成一个环,因此,当n==2时无解,当m<n时无解,其他情况下只需要将所有冰箱的权值加起来*2再将没用的边全部连到权值最小的两个冰箱上即可得到最优解。

代码:

#include <iostream>
#include <algorithm>
 
using namespace std;
 
const int N = 1e3+10;
 
struct node
{
	int w, id;
}a[N];
 
bool cmp(node A,node B)
{
	return A.w < B.w;
}
 
int main()
{
	ios::sync_with_stdio(false);
	cin.tie(0), cout.tie(0);
	int T, n, m;
	cin>>T;
	while(T--){
		cin>>n>>m;
		for(int i = 0; i < n; ++i){
			a[i].id = i+1;
			cin>>a[i].w;
		}
		if(m < n) cout<<-1<<'\n';
		else if(n == 2){
			cout<<-1<<'\n';
		}
		else{
			sort(a,a+n,cmp);
			long long ans = 0;
			for(int i = 0; i < n; ++i)
				ans += a[i].w;
			ans *= 2;
			ans += (m-n)*(a[0].w+a[1].w);
			cout<<ans<<'\n';
			for(int i = 0; i < n; ++i){
				cout<<a[i].id<<' '<<a[(i+1)%n].id<<'\n';
			}
			for(int i = 0; i < (m-n); ++i)
				cout<<a[0].id<<' '<<a[1].id<<'\n';
		}
	}
	return 0;
}

C:League of Leesins

题意:有一个长度为n的1~n的排列,现在将序列中每三个连续的元素提取出来形成一个三元组,三元组内部的元素顺序不定,现在给你n-2个三元组,要求你输出任何一个可行的原序列。

思路:可以确定的是原序列的头部和尾部元素只会在三元组中出现一次,头部元素的后继元素及尾部元素的前驱元素只会在三元组中出现两次,因此我们可以根据这个性质来确定原序列中的前两个元素,然后因为每个三元组都是独一无二的,所以可以跟据已经得到的两个元素来推导下一个元素,直至结尾。

代码:

#include <iostream>
#include <vector>
#include <set>
 
using namespace std;
 
const int N = 1e5+10;
 
struct tripe
{
	int a, b, c;
}Tripe[N];
 
int vis[N], Vis[N];
std::vector<int> Link[N];
std::vector<int> ans;
set <int> st;
 
int main()
{
	ios::sync_with_stdio(false);
	cin.tie(0), cout.tie(0);
	int n, s;
	cin>>n;
	for(int i = 1; i <= n-2; ++i){
		cin>>Tripe[i].a>>Tripe[i].b>>Tripe[i].c;
		vis[Tripe[i].a] += 1;
		vis[Tripe[i].b] += 1;
		vis[Tripe[i].c] += 1;
		Link[Tripe[i].a].push_back(i);
		Link[Tripe[i].b].push_back(i);
		Link[Tripe[i].c].push_back(i);
	}
	for(int i = 1; i <= n; ++i){
		if(vis[i] == 1) s = i;
	}
	for(int i = 1; i <= n; ++i)
		vis[i] = 0;
	int s1, s2, s3, len1, len2, len3;
	vis[Link[s][0]] = 1;
	s1 = Tripe[Link[s][0]].a;
	s2 = Tripe[Link[s][0]].b;
	s3 = Tripe[Link[s][0]].c;
	Vis[s1] = Vis[s2] = Vis[s3] = 1;
	len1 = Link[s1].size();
	len2 = Link[s2].size();
	len3 = Link[s3].size();
	if(len1 < len2 && len1 < len3){
		ans.push_back(s1);
		if(len2 < len3){
			ans.push_back(s2);
			ans.push_back(s3);
			s1 = s2;
			s2 = s3;
		}
		else{
			ans.push_back(s3);
			ans.push_back(s2);
			s1 = s3;
		}
	}
	else if(len2 < len1 && len2 < len3){
		ans.push_back(s2);
		if(len1 < len3){
			ans.push_back(s1);
			ans.push_back(s3);
			s2 = s3;
		}
		else{
			ans.push_back(s3);
			ans.push_back(s1);
			s2 = s1;
			s1 = s3;
		}
	}
	else{
		ans.push_back(s3);
		if(len1 < len2){
			ans.push_back(s1);
			ans.push_back(s2);
		}
		else{
			ans.push_back(s2);
			ans.push_back(s1);
			swap(s1,s2);
		}
	}
	for(int i = 0; i < n-3; ++i){
		st.clear();
		int t;
		len1 = Link[s1].size();
		for(int i = 0; i < len1; ++i){
			if(vis[Link[s1][i]] == 0)
				st.insert(Link[s1][i]);
		}
		len2 = Link[s2].size();
		for(int i = 0; i < len2; ++i){
			if(vis[Link[s2][i]] == 0){
				if(st.find(Link[s2][i]) != st.end())
					t = Link[s2][i];
			}
		}
		vis[t] = 1;
		if(Vis[Tripe[t].a] == 0)
			s3 = Tripe[t].a;
		if(Vis[Tripe[t].b] == 0)
			s3 = Tripe[t].b;
		if(Vis[Tripe[t].c] == 0)
			s3 = Tripe[t].c;
		ans.push_back(s3);
		Vis[s3] = 1;
		s1 = s2;
		s2 = s3;
	}
	for(int i = 0; i < n; ++i)
		cout<<ans[i]<<' ';
	return 0;
}

D:Feeding Chicken

题意:有一个n*m的农场,其中有些格子有米,有些则是空地,现在有一下规则:

1,每个空地都要属于一只鸡

2,一只鸡的领土中至少有一块是有米的

3,鸡的领土必须是连续的

要求你在满足上述规则的情况下,将鸡的含米土地数量的最大差值最小化。输出满足条件的土地分配方案。

思路:可以将农场看成一个螺旋状的回路,然后每只鸡最多分到sum/k+1数量的含米土地,基于这个进行dfs,就可以很好地解决问题了。

ps:这题在比赛时思路出得挺快的,但是dfs的代码写了好久才对,导致我在比赛结束后大概一个小时才ac。。。

代码:

#include <iostream>
#include <cstring>
 
using namespace std;
 
const int N = 110;
 
char a[N][N];
int vis[N][N], VIS[N][N];
int n, m, j = 0, f = 0, DIR = 0;
 
void dfs(int t,int pos)
{
	vis[f][j] = 1;
	VIS[f][j] = pos;
	if(a[f][j] == 'R') t -= 1;
	if(t == 0){
		return ;
	}
	for(int i = 0; i < 4; ++i){
		if(DIR == 0){
			if(j < m-1 && vis[f][j+1] == 0){
				j += 1;
				dfs(t,pos); break;
			}
		}
		else if(DIR == 1){
			if(f < n-1 && vis[f+1][j] == 0){
				f += 1;
				dfs(t,pos); break;
			}
		}
		else if(DIR == 2){
			if(j > 0 && vis[f][j-1] == 0){
				j -= 1;
				dfs(t,pos); break;
			}
		}
		else{
			if(f > 0 && vis[f-1][j] == 0){
				f -= 1;
				dfs(t,pos); break;
			}
		}
		DIR = (DIR+1)%4;
	}
}
 
int main()
{
	ios::sync_with_stdio(false);
	cin.tie(0), cout.tie(0);
	int T, k, sum;
	cin>>T;
	while(T--){
		cin>>n>>m>>k;
		j = f = DIR = 0;
		memset(vis, 0, sizeof vis);
		memset(VIS, -1, sizeof VIS);
		sum = 0;
		for(int i = 0; i < n; ++i){
			for(int j = 0; j < m; ++j){
				cin>>a[i][j];
				if(a[i][j] == 'R')
					++sum;
			}
		}
		int Base = sum%k;		
		for(int i = 0; i < k; ++i){
			int t = sum/k;
			if(i < Base) t += 1;
			dfs(t,i);
			for(int q = 0; q < 4; ++q){
				if(DIR == 0){
					if(j < m-1 && vis[f][j+1] == 0){
						j += 1;
						break;
					}
				}
				else if(DIR == 1){
					if(f < n-1 && vis[f+1][j] == 0){
						f += 1;
						break;
					}
				}
				else if(DIR == 2){
					if(j > 0 && vis[f][j-1] == 0){
						j -= 1;
						break;
					}
				}
				else{
					if(f > 0 && vis[f-1][j] == 0){
						f -= 1;
						break;
					}
				}
				DIR = (DIR+1)%4;
			}
		}
		dfs(1,k-1);
		for(int i = 0; i < n; ++i){
			for(int j = 0; j < m; ++j){
				if(VIS[i][j] == -1)
					cout<<-1;
				else if(VIS[i][j] >= 0 && VIS[i][j] <= 9)
					cout<<VIS[i][j];
				else if(VIS[i][j] >= 10 && VIS[i][j] <= 35)
					cout<<(char)(VIS[i][j]-10+'a');
				else
					cout<<(char)(VIS[i][j]-36+'A');
			}
			cout<<'\n';
		}
	}
	return 0;
}

E1:Send Boxes to Alice (Easy Version)

大佬们说是暴力,还没看。

E2:Send Boxes to Alice (Hard Version)

未知。

F:Point Ordering

未知。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值