Contest2681 - 2021ACM俱乐部后备营个人训练赛第16场

Contest2681 - 2021ACM俱乐部后备营个人训练赛第16场

这段时间在乡下渡劫,停电了,所以训练赛没打,补题的时候做的,回归朴质乡村生活

问题 A: 开心的金明

Solution

动态规划,背包

转移方程:

一维:f [m] = max(f [m] ,f [m-v ]+ w);

不会动态规划的,可以去了解一下:
动态规划入门详解+例题P1049装箱问题/62. Unique Paths
有点儿像它的第一个例题

Code

#include <bits/stdc++.h>
 
using namespace std;
 
int main()
{
    
    
    int i,j,n,m,x,y,sum;
    int f[30005];
    cin>>n>>m;
    for(i=1;i<=m;++i)
    {
    
    
        cin>>x>>y;
        sum = x*y;
        for(j=n;j>=x;--j)
        {
    
    
            f[j] = max(f[j],f[j-x]+sum);
        }
    }
    cout<<f[n];
    return 0;
}

问题 B: 数列I

Solution

题目提醒的挺明显的,要用到进制,再仔细一看例子,对于k=3,N=1(二进制:1)—>1,N=2(二进制:10)—>3,N=3(二进制:11)—>4。

简而言之,就是把N转换成二进制,然后把转换后的数按k进制计算

K=3
N  二进制   k进制
N=1->1--->1*30次方
N=2->10--->1*31次方+0*30次方
N=1->11--->1*31次方+1*30次方

Code

#include <bits/stdc++.h>
 
using namespace std;
 
int main()
{
    
    
    int k,n;
    int ans=0;
    int a[11],i,j;
    cin>>k>>n;
    for(i=0;n!=0;++i)
    {
    
    
        a[i] = n%2;
        n /= 2;
    }
    int temp=i-1;
    for(j=temp;j>=0;--j)
    {
    
    
        ans += a[j]*pow(k,temp--);
    }
    cout<<ans;
    return 0;
}

问题 C: Jam的计数法

Solution

小蒟蒻有一点点思路,但是做着做着就把自己绕进去了,然后没出来,于是去看了讲解,小破站找到了一个视频,百度找到了一篇比较详细的bolg

传送门:

b站大学:【NOIP2006PJ】Jam的计数法(count)讲解

blog:[全排列(洛谷1061 Jam的计数法or NOIP 2006 普及组 第三题)](https://www.yuanmas.com/info/DEzkbb02OY.html)

正解:

起始数字为bdfij,要求依次输出后面的5个数字。输出下一个数字就要对这个数字的最低一位进行进位,如果这个数字超出了区间右边界R,则向高一位进位。

bdfij最低一位是j,进一变成k,k对应的数字11超出了右边界R=10,向高一位进位。i进一变成j,但是如果i变成j那么最后一位就不能再为j了(根据题意,数字中的字符没有重复,且从左到右字典序依次增大),那么这时候再向高一位进位,f变成g,剩余h,i,j可以给前两位进行进位。修改字符串。bdfij变成了bdghi,输出然后从最后一位继续做一遍。

Code

#include<bits/stdc++.h>
using namespace std;
int Map[200];
char s[2000];
int ss,t,w;

int main()
{
    
    
	cin>>ss>>t>>w;
	Map[w-1]=t;
	for(int i=w-2;i>=0;i--)
	  Map[i]=Map[i+1]-1;//Map存储最终排序的数字
	cin>>s;
	int len=strlen(s)-1;
	int temp=5;
	while(temp--)
	{
    
    
		for(int i=len;i>=0;i--)
		{
    
    
		   if(s[i]!=Map[i]+'a'-1)
		   //“严格遵循递增!”自个慢慢悟,这个位置很有意思
		   {
    
    
		      s[i]+=1;
		      for(int k=i+1;k<=len;k++)
		         s[k]=s[k-1]+1;
		      for(int i=0;i<=len;i++)
		         cout<<s[i];
		        cout<<endl;
		       break;
		   }
		}
	}
    return 0;
}

问题 D: 明明的随机数

Solution

sort+unique函数,不会的去看---->常用函数(持续更新)

Code

#include<bits/stdc++.h>
using namespace std;
 
int main()
{
    
    
    int n,a[105];
    cin>>n;
    for(int i=0;i<n;++i)
        cin>>a[i];
    sort(a,a+n);
    int cnt = unique(a,a+n)-a;
    cout<<cnt<<endl;
    for(int i=0;i<cnt;++i)
       cout<<a[i]<<" ";
    return 0;
}

问题 E: Fighting over Candies

Solution

水题。

Code

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

int main()
{
    
    
	int a,b,c;
	cin>>a>>b>>c;
	if(a+b==c || a+c==b ||b+c==a)
        cout<<"Yes";
    else
        cout<<"No";
    return 0;
}

问题 F: Snuke’s Coloring 2-1

Solution

水题,理解题意就行。

Code

#include <bits/stdc++.h>

using namespace std;

int main()
{
    
    
    int w,h,n;
    int x,y,a;
    int di,gao;
    cin>>w>>h>>n;
    int x1=0,y1=0;
    int x2=w,y2=h;
    while(n--)
    {
    
    
        cin>>x>>y>>a;
        switch(a)
        {
    
    
            case 1:
            {
    
    
                x1 = max(x,x1);
                break;
            }
            case 2:
            {
    
    
                x2 = min(x,x2);
                break;
            }
            case 3:
            {
    
    
                y1 = max(y,y1);
                break;
            }
            case 4:
            {
    
    
                y2 = min(y,y2);
                break;
            }
        }
    }
    int A = (x2-x1)*(y2-y1);
    if((x1>x2) || (y1>y2))
        cout<<"0";
    else
        cout<<A;
    return 0;
}

问题 G: 1D Reversi

Solution

模拟题,但是感觉有一丢丢贪心的思想在。

注意:他只能将棋子放在左右两端中的任意一断,不能插入在中间

以BWBW为例
    第一次:放一个B在右边-->BWBB
    第二次:放一个W在左边-->WWBB
    第三次:放一个B在左边-->BBBB

Code

#include <bits/stdc++.h>

using namespace std;

int main()
{
    
    
    string s;
    cin>>s;
    int time=0;
    for(int i=0;i<s.size()-1;++i)
        if(s[i]!=s[i+1])
            ++time;
    cout<<time;
    return 0;
}

问题 H: An Invisible Hand

Solution

贪心。

Code

#include <bits/stdc++.h>

using namespace std;

bool cmp(int a,int b)
{
    
    
    return a>b;
}

int main()
{
    
    
    int n,t;//t是用来理解题意的,害
    cin>>n>>t;
    int b=0,time=0;
    int a[100005],maxa[100005],lirun[100005];
    for(int i=1;i<=n;++i)
        cin>>a[i];

    for(int i=n;i>=1;--i)
        maxa[i] = max(maxa[i+1],a[i]);
        //找到售价最贵的地方卖出
        //由于是从第一个镇到第N个镇,所以从后开始找最大的数
    for(int i=1;i<n;++i)
        lirun[++b]=maxa[i+1]-a[i];//求在每个镇上的利润
        
    sort(lirun+1,lirun+1+b,cmp);//排序,找到最大利润lirun[1]
    
    for(int i=1;i<=b;++i)
        if(lirun[i]==lirun[1])
        //如果达到最大利润,则进行此操作
        //由于要最低成本,所以在原来基础上+1,即可(贪心思想)
            ++time;
            
    cout<<time;
    return 0;
}

猜你喜欢

转载自blog.csdn.net/m0_51344172/article/details/113529560