代码源week1

T1:特殊正方形

题目链接:特殊的正方形 - 题目 - Daimayuan Online Judge

题解:

用一个cnt记录打印的圈数,当cnt为奇数时候打印“+”,偶数时候打印“.”

在对应打印函数传入起点k及打印的高度h

代码

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

int n;
char m[105][105];

void pr_1(int h,int k){//h为打印的高度,k为打印的起点
	for(int i=k;i<=h;i++){
		for(int j=k;j<=n-k+1;j++){
			if(i==k||i==h)m[i][j]='+';
			else m[i][k]='+',m[i][n-k+1]='+';
		}
	}
}
void pr_2(int h,int k){
	for(int i=k;i<=h;i++){
		for(int j=k;j<=n-k+1;j++){
			if(i==k||i==h)m[i][j]='.';
			else m[i][k]='.',m[i][n-k+1]='.';
		}
	}
}
int main()
{
	cin>>n;
	int cnt=1;
	for(int i=n;i>=1;i--){
		if(cnt%2)pr_1(i,cnt);
		else pr_2(i,cnt);
		cnt++;
	}
	for(int i=1;i<=n;i++){
		for(int j=1;j<=n;j++){
			cout<<m[i][j];
		}
		cout<<endl;
	}
 	return 0;
}

T2:走楼梯2

题目链接:走楼梯2 - 题目 - Daimayuan Online Judge

题解:

用一个f[i][j]记录走到i级阶梯连续j次走两步的路径数,显然:到达第n级台阶的总路径数是f[n][0]+f[n][1]+f[n][2]

  • 走两步:f[i+2][j+1]当j<2时候可以从f[i][j]转移
  • 走一步:f[i+1][0]可以从f[i][1],f[i][2]和f[i][0]转移
  • 初始化f[0][0]=1;然后从0步开始走

代码

#include<bits/stdc++.h>
using namespace std;
long long n,f[105][4];
int main()
{
	cin>>n;//初始化
	f[0][0]=1;
	for(int i=0;i<=n;i++){
		for(int j=0;j<=2;j++){
			if(j<2){//状态转移
				f[i+2][j+1]+=f[i][j];
				f[i+1][0]+=f[i][j];
			}
			else{
				f[i+1][0]+=f[i][j];
			}
		}
	}
	cout<<f[n][0]+f[n][1]+f[n][2]<<endl;//输出撒花
 	return 0;
}

T3:走路

题目链接:走路 - 题目 - Daimayuan Online Judge

题解:

用f[i][j]表示走i步是否到达坐标为j的位置,用“1”代表能够到达,用"0"代表不能够到达.

若f[i][j]==1且j+a[i]或者j+b[i]小于坐标最大值m则f[i+1][j+a[i]]或f[i+1][j+b[i]]就能到达

最后输出n步之后能够到达的点

代码

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

int n,m;
int a[105],b[105],f[105][100005];
int main()
{
	cin>>n>>m;
	for(int i=1;i<=n;i++){
		cin>>a[i]>>b[i];
	}
	f[0][0]=1;//从0步开始走
	for(int i=0;i<n;i++){
		for(int j=0;j<=m;j++){
			if(f[i][j]&&j+b[i]<=m)f[i+1][j+b[i+1]]=1;
			if(f[i][j]&&j+a[i]<=m)f[i+1][j+a[i+1]]=1;
		}
	}
	for(int i=0;i<=m;i++){
		if(f[n][i]==1)cout<<1;
		else cout<<0;
	}
 	return 0;
}

T4:简单分数统计

题目链接:简单分数统计 - 题目 - Daimayuan Online Judge

模拟题,开水

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

int n,m,k,sum[205];
string id[205];
struct x{
	int s;
	string title;
}x[205];
int main()
{
	cin>>n>>m>>k;
	for(int i=1;i<=n;i++)cin>>id[i];
	for(int i=1;i<=m;i++)cin>>x[i].title>>x[i].s;
	for(int i=1;i<=k;i++){
		string a,b,c;
		cin>>a>>b>>c;
		if(c=="WA")continue;
		int flag=0,now=0;
		for(int j=1;j<=m;j++){
			if(b==x[j].title){
				flag=1;now=x[j].s;
				break;
			}
		}
		if(flag){
			for(int j=1;j<=n;j++){
				if(a==id[j]){
					sum[j]+=now;
					break;
				}
			}
		}
	}
	for(int i=1;i<=n;i++){
		cout<<id[i]<<' '<<sum[i]<<endl;
	}

 	return 0;
}

T5:Alice的德州扑克

题目链接:Alice的德州扑克 - 题目 - Daimayuan Online Judge

恶心的模拟题~~~,用建立结构体一个一个检查就行了

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

struct pai{
	int ditgit,color;
}p[10];
string rk[7]={"ROYAL FLUSH","STRAIGHT FLUSH","FOUR OF A KIND","FULL HOUSE","FLUSH", "STRAIGHT","FOLD"};
bool RF(){
	int x=p[1].ditgit,y=p[1].color;
	if(p[5].ditgit!=14)return 0;
	for(int i=2;i<=5;i++){
		if(x+1!=p[i].ditgit||y!=p[i].color)return 0;
		x++;
	}
	return 1;
}
bool SF(){
	int x=p[1].ditgit,y=p[1].color;
	for(int i=2;i<=5;i++){
		if(x+1!=p[i].ditgit||y!=p[i].color)return 0;
		x++;
	}
	return 1;
}
bool FK(){
	if(p[1].ditgit==p[4].ditgit)return 1;
	else if(p[2].ditgit==p[5].ditgit)return 1;
	else return 0;
}
bool FH(){
	if(p[1].ditgit==p[3].ditgit&&p[4].ditgit==p[5].ditgit)return 1;
	else if(p[1].ditgit==p[2].ditgit&&p[3].ditgit==p[5].ditgit)return 1;
	else return 0;
}
bool F(){
	int c=p[1].color;
	for(int i=2;i<=5;i++){
		if(c!=p[i].color)return 0;
	}
	return 1;
}
bool S(){
	int x=p[1].ditgit;
	for(int i=2;i<=5;i++){
		if(x+1!=p[i].ditgit)return 0;
		x++;
	}
	return 1;
}

int main()
{
	for(int i=1;i<=5;i++)cin>>p[i].ditgit;
	for(int i=1;i<=5;i++)cin>>p[i].color;
	if(RF())cout<<rk[0];
	else if(SF())cout<<rk[1];
	else if(FK())cout<<rk[2];
	else if(FH())cout<<rk[3];
	else if(F())cout<<rk[4];
	else if(S())cout<<rk[5];
	else cout<<rk[6];
 	return 0;
}

T6:订单编号

最让人头疼的一题,呜呜~~~

题目链接:订单编号 - 题目 - Daimayuan Online Judge

题解:(做这种难题确实让人收获颇盛,但是很耗时间)

一个个知识点梳理:

1:stl容器之set:在集合中所有的元素只能出现一遍,并且按照元素的值从小到大排序

  • set.insert(ele)向集合中插入一个元素ele
  • set.erase(index/ele)删除集合中迭代器index指向的元素,或者直接删除元素ele
  • set.lower_bound(key)返回集合中第一个大于等于key的迭代器
  • set.upper_bound(key)返回集合中第一个大于key的迭代器

2:当set与pair组合使用时候,low_bound查找的是first的值,如果first相同情况下,才会查找second

正文:

为啥要反着储存set(2e9,1)而不是set(1,2e9)呢?

我是这莫理解的:如果正向储存,查找到的总是一个大于x的数的迭代器位置,这样的话是始终找不到一个区间(L,R)包含x的情况

情况1:当查找到的区间最小值L小于等于x时候,说明这个订单编号未被使用,删除这个it迭代器对应的元素将区间(L,R)分为两段(L,x-1)和(x+1,R)

情况2:当查找到区间的最小值L大于x时候,说明这个订单编号已经被使用过了,只能使用区间中第一个大于x的订单编号L,然后将区间(L,R)变化为(L+1,R);

代码段

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

int n;
set<pair<int,int> > s;

void Insert(int l,int r){
	if(l>r)return;
	s.insert(make_pair(r,l));
}

int main()
{
	scanf("%d",&n);
	s.insert(make_pair(2e9,1));//反向储存
	for(int i=1;i<=n;i++){
		int x;
		scanf("%d",&x);
		auto it=s.lower_bound(make_pair(x,0));//查找第一个大于x的pair.first()迭代器位置
		int l=it->second,r=it->first;
		s.erase(it);
		if(l<=x){
			printf("%d ",x);
			Insert(l,x-1);//裂开区间
			Insert(x+1,r);
			
		}
		else{
			printf("%d ",l);
			Insert(l+1,r);
		}
	}
	
 	return 0;
}

T7:饿饿饭饭

题目链接:http://oj.daimayuan.top/course/11/problem/463

题解:二分答案一共打了多少轮饭,然后将最后一轮的情况,进行模拟队列(真滴6)

代码段:

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

int n,a[100005],c[100005];
long long k;
long long res(int x){
	long long sum=0;
	for(int i=1;i<=n;i++){
		if(a[i]<=x)sum+=a[i];
		else sum+=x;
	}
	return sum;
}
int main()
{
	cin>>n>>k;
	long long s=0;
	for(int i=1;i<=n;i++)cin>>a[i],s+=a[i];
	if(s<k){
		cout<<-1;
		return 0;
	}
	int L=0,R=1e9;
	while(L+1<R){二分轮数
		int mid=(L+R)/2;
		if(res(mid)<=k)L=mid;
		else R=mid;
	}
    //模拟最后一轮打饭情况
	k-=res(L);
	int tot=0;
	for(int i=1;i<=n;i++){
		if(a[i]>L)c[++tot]=i;
	}
	for(int i=k+1;i<=tot;i++){
		cout<<c[i];
	}
	for(int i=1;i<=k;i++){
		if(a[c[i]]!=L+1)
		cout<<c[i];
	}
	return 0;
}

T8:最大和上升子序列

题目链接:最大和上升子序列 - 题目 - Daimayuan Online Judge

思路:

当i前面的数满足小于a【i]时候,更新对应于f[i]的最佳答案

代码段:

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

int n,a[1005],f[1005],vis[100005],ans;
int main()
{
	cin>>n;
	for(int i=1;i<=n;i++)
	{
		cin>>a[i];
		f[i]=a[i];//初始化
	}

	for(int i=2;i<=n;i++){
		for(int j=1;j<i;j++){//循环i前面的数
			if(a[j]<a[i])f[i]=max(f[i],f[j]+a[i]);//更新f[i]答案
			ans=max(ans,f[i]);//搜索最大答案
		}
	}
	ans=max(ans,f[1]);
	cout<<ans<<endl;
 	return 0;
}

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值