填涂颜色(找规律)

思路没想到的原因

没有开longlong longlong!以后数据范围一定要认真地看清楚

思路

找规律:

n/mn/m 2 3 4
3 k=3k=3 \rightarrow 66 k=24k=2 \rightarrow 4 k=24k=2\rightarrow4
4 k=38k=3 \rightarrow 8 k=39k=3 \rightarrow 9 k=516k=5 \rightarrow 16
5 k=510k=5 \rightarrow 10 k=412k=4 \rightarrow 12 k=39k=3 \rightarrow 9

最后的公式是:min(n,k)min(m,k)min(n,k)*min(m,k)。还有,记得开longlong longlong

代码

#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记录每艘船的信息,每新进一艘船就将其和队首元素作比较,如果大于等于8640086400遍历数组,将每位乘客的国籍编号在w数组中减 11,如果发现有一次减完了,则 s--

接下来将当前船只入队并遍历当前船只的所有乘客 v[i],将每个乘客在 s 中的变量加 11,如果发现某个国籍的人在加 11 之前是 00,那么说明有新国籍的人进来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 的条件要变,首先要判断边界,这里有一个细节,nxny的边界为 03000 \sim 300,因为输入的 x, y 的最大值为 300300。其次遍历当前的步数是否小于当前位置流星砸下来的时间(因为步数就是用时),如果都满足,就新增当前节点。
  • 再把nxny,与当前的步数( 记得加上一 )重新存到队列里面。

然后,循环判断这个坐标是否满足永远不会被流星摧毁的条件,也就是走到,取两者(指原本的答案走到当前合法位置的步数)的最小值更新答案。

最后,如果答案还是为初始值,输出-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;
}

谢谢