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*3的0次方
N=2->10--->1*3的1次方+0*3的0次方
N=1->11--->1*3的1次方+1*3的0次方
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;
}