AtCoder Beginner Contest 345(A~D)

A.

简单模拟

#include<bits/stdc++.h>
using namespace std;

int main(){
	string s;
	cin>>s;
	if(s.front()!='<'||s.back()!='>') puts("No");
	else{
		bool flag=true;
		for(int i=1;i<s.size()-1;i++)
			if(s[i]!='='){
				flag=false;
				break;
			}
		if(flag) puts("Yes");
		else puts("No");
	}
	return 0;
}

B.

正整数a/b上取整,只需a+b-1再除以b下取整

负数a/b上取整, 直接a/b即可

#include<bits/stdc++.h>
using namespace std;

int main(){
	long long x;
	cin>>x;
	if(x>0) x+=9;
	cout<<x/10<<endl;
	return 0;
}

C.

分析:

对于任意一对(i, j),i != j,如果s[i] != s[j]则两者交换位置一定会产生一种新的字符串,如果s[i] == s[j]则不变。

所以我们只需统计a~z每个字母的出现的次数,再两层循环遍历a~z,对num[i]*num[j]求和(i != j,0<=i, j<26),这里对于数对(i, j)与(j, i) 其实是属于一种情况,不应重复计算。

特别的只要a~z中有字母出现2次及以上,则至少存在一种可以进行相同字母交换位置,得到原来的字符串,也算一种字符串。

#include<bits/stdc++.h>
using namespace std;

int num[26];
string s;

int main(){
	cin>>s;
	long long res=0;
	for(auto c:s){
		num[c-'a']++;
		if(num[c-'a']>1) res=1;
	}
	for(int i=0;i<26;i++)
		for(int j=i;j<26;j++)
			if(i!=j&&num[i]&&num[j])
				res+=num[i]*num[j];
	cout<<res<<endl;
	return 0;
}

D. DFS+剪枝

分析:

优化1:将每块瓷砖的面积从大到小排序,先放大的再放小的

优化2:计算所有瓷砖的总面积,如果总面积不足以完全覆盖网格则直接打印“No”

优化3:在放第u块瓷砖之前,判断是否剩下的瓷砖面积总和+当前已经覆盖的面积大于等于网格总面积,如果小于则不用再继续往下搜了,直接return false

#include<bits/stdc++.h>
#define PII pair<int,int>
#define a first
#define b second
using namespace std;
const int N=11;

int n,m,q;
vector<PII> s;
bool st[N][N];
int w[N];

bool cmp(PII x,PII y){
	return x.a*x.b>y.a*y.b;
}

bool check(int x,int y,int a,int b){
	for(int i=x;i<x+a;i++)
		for(int j=y;j<y+b;j++)
			if(st[i][j]){
				return false;
			}
	return true;
}

bool isSuccess(){
	for(int i=0;i<n;i++)
		for(int j=0;j<m;j++)
			if(!st[i][j]) return false;
	return true;
}

void draw(int x,int y,int a,int b){
	for(int i=x;i<x+a;i++)
		for(int j=y;j<y+b;j++)
			st[i][j]=true;
}

void undraw(int x,int y,int a,int b){
	for(int i=x;i<x+a;i++)
		for(int j=y;j<y+b;j++)
			st[i][j]=false;
}

bool dfs(int u,int cur){
	if(isSuccess()) return true;
	if(cur+w[u]<n*m) return false;
	if(u==q) return false;
	
	int a=s[u].a,b=s[u].b;
	for(int i=0;i<n;i++){
		for(int j=0;j<m;j++){
			if(st[i][j]) continue;
			
			if(i+a<=n&&j+b<=m&&check(i,j,a,b)){
				draw(i,j,a,b);
				if(dfs(u+1,cur+a*b)) return true;
				undraw(i,j,a,b);
			}
			if(a!=b&&i+b<=n&&j+a<=m&&check(i,j,b,a)){
				draw(i,j,b,a);
				if(dfs(u+1,cur+a*b)) return true;
				undraw(i,j,b,a);
			}
		}
	}
	return dfs(u+1,cur);
}

int main(){
	cin>>q>>n>>m;
	int sum=0;
	for(int i=0;i<q;i++){
		int x,y;
		cin>>x>>y;
		sum+=x*y;
		s.push_back({x,y});
	}
	sort(s.begin(),s.end(),cmp);
	for(int i=s.size()-1;i>=0;i--)
		w[i]=w[i+1]+s[i].a*s[i].b;
		
	if(sum>=n*m&&dfs(0,0)) cout<<"Yes"<<endl;
	else cout<<"No"<<endl;
	return 0;
}

评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

菜鸡本鸡orz

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值