- 赵一静 的博客
八月暑期集训8月23日DAY17题解
- @ 2024-8-23 15:39:19
填涂颜色(找规律)
思路没想到的原因
没有开 !以后数据范围一定要认真地看清楚。
思路
找规律:
| 2 | 3 | 4 | |
|---|---|---|---|
| 3 | |||
| 4 | |||
| 5 |
最后的公式是:。还有,记得开 。
代码
#include <bits/stdc++.h>
#define int long long//永远的痛!!!
using namespace std;
signed main(){
freopen("color.in","r",stdin);
freopen("color.out","w",stdout);
int n,m,k;
cin >>n>>m>>k;
cout <<min(n,k)*min(m,k);
return 0;
}
密码(模拟)
思路没想到的原因
不知道怎样去处理密钥重复使用。导致没有得分。
思路
首先,把密钥都转成小写字母,再用循环判断,如果密钥的长度不等于密文的长度,那么把密钥复制在原来密钥的后面;
然后把答案数组赋值为密文,枚举my[i]-'a',每次-1,如果当前的字符不是字母,那就赋值为小写或大写字母z。因为说明它超出边界了,就像'z'+1='[',而不是字母。
最后输出答案数组即可。
代码
#include <bits/stdc++.h>
using namespace std;
int main(){
freopen("vigenere.in","r",stdin);
freopen("vigenere.out","w",stdout);
string my1,mw;
getline(cin,my1);
getline(cin,mw);
string s=mw;
for(int i=0;i<my1.size();i++){
if(my1[i]>='A'&&my1[i]<='Z'){
my1[i]=my1[i]-'A'+'a';
}
}
string my;
for(int i=0;i<my1.size();){
if(my.size()!=mw.size()){
if(i+1==my1.size()){
my.push_back(my1[i]);
i=0;
}else{
my.push_back(my1[i]);
i++;
}
}else{
break;
}
}
for(int i=0;i<s.size();i++){
for(int j=1;j<=my[i]-'a';j++){
s[i]-=1;
if(s[i]<'a'&&s[i]>'Z'){
s[i]='z';
}
if(s[i]<'A'){
s[i]='Z';
}
}
}
cout <<s;
return 0;
}
海港(模拟)
思路
首先需要一个变量记录每种国籍的人有多少人,也要用一个数组w记录有多少种不同的国籍,再用x记录每艘船的信息,每新进一艘船就将其和队首元素作比较,如果大于等于则遍历数组,将每位乘客的国籍编号在w数组中减 ,如果发现有一次减完了,则 s--。
接下来将当前船只入队并遍历当前船只的所有乘客 v[i],将每个乘客在 s 中的变量加 ,如果发现某个国籍的人在加 之前是 ,那么说明有新国籍的人进来,s++。
最后每次输出s即可。
代码
#include <bits/stdc++.h>
using namespace std;
const int tt=3e5+10;
int w[tt],x[tt],y[tt];
int main(){
freopen("port.in","r",stdin);
freopen("port.out","w",stdout);
int n;
int ans=0,res=1,op=0;
cin >>n;
while(n--){
int t,k;
cin >>t>>k;
while(k--){
y[++op]=t;
cin >>x[op];
if(!w[x[op]]){
ans++;
}
w[x[op]]++;
}
while(t-y[res]>=86400){
if(--w[x[res++]]==0){
ans--;
}
}
cout <<ans<<endl;
}
return 0;
}
流星雨(bfs广搜)
思路没想到的原因
根本没有去认真地思考这一题,去搞第二题去了。以后题目还是要思考一下的。
思路
纯广搜模板,只不过需要改一点条件:
- 结束的条件需要改变,只要当前走到的
b[x][y]为0x3f3f3f3f说明走到了安全的地方,直接return。 - 广搜往四个方向搜时,
continue的条件要变,首先要判断边界,这里有一个细节,nx和ny的边界为 ,因为输入的x, y的最大值为 。其次遍历当前的步数是否小于当前位置流星砸下来的时间(因为步数就是用时),如果都满足,就新增当前节点。
- 再把
nx,ny,与当前的步数( 记得加上一 )重新存到队列里面。
然后,循环判断这个坐标是否满足永远不会被流星摧毁的条件,也就是走到,取两者(指原本的答案与走到当前合法位置的步数)的最小值更新答案。
最后,如果答案还是为初始值,输出-1,否则,输出答案。
代码
#include <bits/stdc++.h>
using namespace std;
int mp[350][350];
int b[3100][3100];
queue<int> x_1,y_1,q;
int d[5][2]={{-1,0},{1,0},{0,-1},{0,1}};
void bfs(){
while(!q.empty()){
int xx=x_1.front();
x_1.pop();
int yy=y_1.front();
y_1.pop();
int res=q.front();
q.pop();
for(int i=0;i<4;i++){
int nx=xx+d[i][0],ny=yy+d[i][1];
if(nx<0||nx>301||ny<0||ny>301) continue;
if(mp[nx][ny]<=res+1&&mp[nx][ny]!=0x3f3f3f3f) continue;
if(res+1<b[nx][ny]){
b[nx][ny]=res+1;
q.push(res+1);
x_1.push(nx);
y_1.push(ny);
}
}
}
}
int main(){
freopen("meteor.in","r",stdin);
freopen("meteor.out","w",stdout);
memset(mp,0x3f,sizeof mp);
memset(b,0x3f,sizeof b);
int m;
cin >>m;
for(int i=1;i<=m;i++){
int x,y,t;
cin >>x>>y>>t;
mp[x][y]=min(mp[x][y],t);
mp[x+1][y]=min(mp[x+1][y],t);
mp[x][y+1]=min(mp[x][y+1],t);
if(x-1>=0) mp[x-1][y]=min(mp[x-1][y],t);
if(y-1>=0) mp[x][y-1]=min(mp[x][y-1],t);
}
x_1.push(0);
y_1.push(0);
q.push(0);
bfs();
int ans=0x3f3f3f3f;
for(int i=0;i<=301;i++){
for(int j=0;j<=301;j++){
if(b[i][j]!=0x3f3f3f3f&&mp[i][j]==0x3f3f3f3f){
ans=min(ans,b[i][j]);
}
}
}
if(ans==0x3f3f3f3f) cout <<-1;
else cout <<ans;
return 0;
}