week13 代码源每日一题Div2

1、特殊的正方形

在这里插入图片描述

思路:

这题用二维数组一圈一圈地存更简便,但我当时没想到,所以我直接暴力解题,一行一行的存。不要学我暴力解题!代码稍微看看就行了,不太记得自己的代码思路了,可以说思路很乱,所以代码请不要深究。

#include<iostream>
using namespace std;
int main()
{
	int n;
	cin>>n;
	
	for(int i=0;i<n;i++)cout<<"+";	//先输出第一行
	cout<<endl;
	
	int u;					//u表示除了第一行和最后一行,中间行数的均值
	if(n%2==0)u=(n-2)/2;
	else u=(n-2)/2+1;
	for(int j=1;j<=n-2;j++)//现只对中间的行做分析,故j=1表示第二行,以下称为第j行
	{	
		int m=1,js;		
		if(n%2==0)
		{
			if(j<=u)js=j;
			else js=2*u+1-j;
		}
		else 
		{
			if(j<=u)js=j;
			else js=2*u-j;
		}
		int u1=js;
		while(m<=n)
		{
			if(m%2==1&&js>0)
			{
				cout<<"+";
				js--;
			}
			else if(m%2==0&&js>0)
			{
				cout<<".";
				js--;
			}
			else if(js==0&&n-m>=u1)
			{
				if(u1%2==1)
				{
					cout<<".";
				}
				else cout<<"+";
			}
			else 
			{
				if(n%2==0)
				{
					if(m%2==0)cout<<"+";
					else cout<<".";
				}
				else
				{
					if(m%2==0)cout<<".";
					else cout<<"+";
				}
			}
			
			m++;
		}
		cout<<endl;
	}
	for(int i=0;i<n;i++)cout<<"+";
	return 0;
 } 

2、走楼梯2

在这里插入图片描述

思路:

典型的动态规划题。本题关键在于找到状态转移方程
dp[i][0] = dp[i-1][0]+dp[i-1][1]+dp[i-1][2]
注意:当站在第 k 阶时,要考虑三种情况:
1、一步一阶登上第 k 阶
2、一步两阶,且第一次是一步两阶
3、一步两阶,且连续两次是一步两阶

#include<iostream>
#include<algorithm>
#include<cstdio>
#include<cstring>
#include<string>
#include<cmath> 
#include<vector>
#include <iomanip>
using namespace std;
typedef long long  ll;
const int inf = 0x3f3f3f3f;
#define fo(x) for(int i = 1;i<=x;++i)
#define ios ios::sync_with_stdio(false);cin.tie(0), cout.tie(0)
const int N = 1e6+9;
ll dp[55][5];
int main()
{
	ios;
	int n;
	cin>>n;
	dp[1][0] = 1;
	dp[1][1] = 0;
	dp[1][2] = 0;
	dp[2][0] = 1;
	dp[2][1] = 1;
	dp[2][2] = 0;
	for(int i = 3;i<=n;i++)
	{
		dp[i][0] = dp[i-1][0]+dp[i-1][1]+dp[i-1][2];
		dp[i][1] = dp[i-2][0];
		dp[i][2] = dp[i-2][1];
	}
	cout<<dp[n][0]+dp[n][1]+dp[n][2]<<"\n";
}

3、走路

在这里插入图片描述

思路:

如果只是把所有情况都考虑一次,这样会超时。可以用动态规划的方法解答,同样的,需找到状态转移方程st[i][j] = st[i - 1][j - a]

#include<iostream>

using namespace std;

const int N = 100010;

int n, m;
bool st[110][N];

int main()
{
    cin >> n >> m;
    st[0][0] = true;
    for ( int i = 1; i <= n; i ++ )
    {
        int a, b;
        cin >> a >> b;
        if (a > b) swap(a, b);
        for ( int j = m; j >= a; j -- )
        {
            st[i][j] = st[i - 1][j - a];
            if (j >= b) st[i][j] = st[i - 1][j - b];
        }
    }

    for ( int i = 0; i <= m; i ++ )
    {
        if (st[n][i]) cout << "1";
        else cout << "0";
    }

    return 0;
}

4、简单分数统计

在这里插入图片描述

思路:

这题很简单,就是模拟,按照题目说的做就行了。

#include<iostream>
using namespace std;
struct fr			//保存好朋友的数据
{
	string id;		//名字
	int s;			//分数
};
struct q			//保存题目的情况
{
	string q1;		//题目名称
	int q2;			//题目分数
};
int main()
{
	int n,m,k;
	cin>>n>>m>>k;
	fr a[n+1];
	q b[m+1];
	
	for(int i=1;i<=n;i++)
	{
		cin>>a[i].id;
		a[i].s=0;
	}
	for(int i=1;i<=m;i++)
	{
		cin>>b[i].q1>>b[i].q2;
	}
	for(int i=1;i<=k;i++)
	{
		string name,sub,r;
		cin>>name>>sub>>r;
		for(int j=1;j<=n;j++)
		{
			if(a[j].id==name&&r=="AC")
			{
				for(int h=1;h<=m;h++)		//判断对应的题目加对应的分数
				{
					if(b[h].q1==sub)a[j].s+=b[h].q2;
				} 
			}
		}
	}
	
	for(int i=1;i<=n;i++)
		cout<<a[i].id<<' '<<a[i].s<<endl;
	
	
	return 0;
} 

5、Alice的德州扑克

在这里插入图片描述

思路:

这题也比较简单,也是模拟,注意看清楚题目、注意牌型有大小之分。

#include<iostream>
using namespace std;
int main()
{
	int a[6],b[6],c[15]={0}; 	//a数组用于表示牌的点数,b表示花色,c用于统计每种牌有多少张
	int flag1=0,flag2=0,flag3=0;
	for(int i=1;i<=5;i++)
	{
		cin>>a[i];
		c[a[i]]++;
	}
	for(int i=2;i<=14;i++)
	{
		if(c[i]>=4)				//至少四张牌的点数相同
		{
			flag1=4;
		}
		else if(c[i]==3)		//至少三张牌的点数相同
		{
			flag2=3;
		}
		else if(c[i]==2)		//出现有两张牌点数相同的情况
		{
			flag3=2;
		}
	}
	for(int i=1;i<=5;i++)cin>>b[i];
	
	if(a[2]-a[1]==1&&a[3]-a[2]==1&&a[4]-a[3]==1&&a[5]-a[4]==1)
	{
		if(b[1]==b[2]&&b[2]==b[3]&&b[3]==b[4]&&b[4]==b[5])
		{
			if(a[5]==14)cout<<"ROYAL FLUSH";
			else cout<<"STRAIGHT FLUSH";
		}
		else cout<<"STRAIGHT";
	}
	else if(flag1==4)cout<<"FOUR OF A KIND";
	else if(flag3==2&&flag2==3)cout<<"FULL HOUSE";
	else if(b[1]==b[2]&&b[2]==b[3]&&b[3]==b[4]&&b[4]==b[5])
	{
		cout<<"FLUSH";
	}
	else cout<<"FOLD";
	return 0;
}

6、订单编号

在这里插入图片描述

思路:

set用法:set排序遇到pair,lower_bound查的是set的first,不会查second,除非first相等才会按照second来排。查到的时候只需要观察是否在区间内即可,(如果区间的最小值大于等于x就直接输出x,如果区间最小值大于x就输出区间最小值)查到之后将该点去掉分成两个区间。插入pair时需要用insert,并且带上大括号{}。
(C++中set用法详解)

#include <bits/stdc++.h>
 
using namespace std;
 
typedef pair<int, int> pii;
typedef long long ll;
typedef vector<int> vi;
//#define int long long
#define fir first
#define sec second
#define all(x) (x).begin(), (x).end()
#define sz(x) (int)x.size()
#define rep(i, l, r) for (int i = l; i <= r; ++i)
#define repd(i, l, r) for (int i = l; i >= r; --i)
#define pb push_back
 
 
set<pair<int,int> >se;
 
void myinsert(int l,int r)
{
    if(r<l)return;
    se.insert({r,l});
}
 
int main() {
    ios_base::sync_with_stdio(false);
    cin.tie(NULL);			//对cin解绑
    int n;
    cin>>n;
    se.insert({2e9,1});
    rep(i,1,n)
    {
        int x;
        cin>>x;
        auto it=se.lower_bound({x,0});
        if(it->sec <=x)
        {
            cout<<x<<" ";
            myinsert(it->sec,x-1);
            myinsert(x+1,it->fir);
            se.erase(it);
        }
        else
        {
            cout<<it->sec<<" ";
            myinsert(it->sec+1,it->fir);
            se.erase(it);
        }
    }
    return 0;
}

7、饿饿 饭饭

在这里入图片描述

思路:

用一个map记录所有学生的饭量的出现次数,因为map的自动排序功能,使得小饭量的会排在前面。把学生的饭量按照输入顺序存入数组中,同时记录所有饭量的总和,如果总和小于k,就直接输出-1。开始模拟打饭,每次我们给全体喂当前打饭人中饭量最少的分量,我们直接从map中取出即可,喂完后,饭量最少的人就离开了队伍,我们要准备一个len来记录队伍剩余的人,以此往复,当剩下的饭不够喂满最低饭量的人时结束循环,我们把剩余饭量k对len取余,这样剩下的饭量就只够再打一趟饭了,我们遍历队伍,如果有没吃饱的人就给他一份饭,然后他把存入另一个数组里(这个数组就充当队尾),要注意,如果有人在此过程中吃饱了,就不存入数组里。最后先输出队伍剩余的人,在输出队尾数组里的人。
(思路来源:https://blog.csdn.net/fnmdpnmsl/article/details/123283788)

#include<iostream>
using namespace std;
#include<vector>
#include<algorithm>
#include<set>
#include<string>
#include<map>
#include<unordered_map>
#include<stack>

typedef long long ll;
typedef pair<int, int>PII;


int main()
{
	map<ll, int>mymap;
	ll n, k;
	ll sum = 0;
	cin >> n >> k;
	vector<ll>v(n + 1);
	for (int i = 1; i <= n; i++)
	{
		cin >> v[i];
		sum += v[i];
		mymap[v[i]]++;
	}
	if (sum < k)
	{
		cout << -1 << endl;
		return 0;
	}
	ll len = n, res = 0, algo = 0;
	auto it = mymap.begin();
	while (it!=mymap.end()&&k >= (it->first - algo) * len)
	{
		k -= (it->first - algo) * len;
		len -= it->second;
		res = it->first;
		algo = it->first;
		it++;
		if (len == 1)
			cout << " ";
	}
	if (len == 0)
	{
		return 0;
	}
	k %= len;
	int ans = 1;
	vector<ll>back;
	bool flag = false;
	for (int i = ans; i <= n && k; i++)
	{
		flag = false;
		if (v[i] == res + 1)
		{
			k--;
			ans = i;
			flag = true;
		}
		else if (v[i] > res)
		{
			back.push_back(i);
			ans = i;
			k--;
			flag = true;
		}
	}
	if (flag)ans++;
	for (int i = ans; i <= n; i++)
	{
		if (v[i] > res)cout << i << " ";
	}
	for (int i = 0; i < back.size(); i++)cout << back[i] << " ";

	return 0;
}

8、任务分配

在这里插入图片描述

思路:

典型的动态规划题。对于每一个任务,只有选或不选两种情况。

#include<iostream>
#include<algorithm>
using namespace std;

int main()
{
	int n,maxi=0;
	cin>>n;
	int s[1001],e[1001],w[1001];
	
	for(int i=1;i<=n;i++)
	{
		cin>>s[i]>>e[i]>>w[i];
		if(e[i]>maxi)maxi=e[i];		//maxi表示最后一个任务结束的时间
	}
	int f[1001]={0};		//f[i]表示i时间内能获得的最大收益 
	for(int i=1;i<=maxi;i++)
	{
		f[i]=max(f[i],f[i-1]);
		for(int j=1;j<=n;j++)
		{
			if(i==s[j])
			{
				f[e[j]]=max(f[e[j]],f[i]+w[j]);		//选还是不选
			}
		}
	}
	cout<<f[maxi];
	
	return 0;
}
  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值