藍橋杯第十一屆軟件類校內模擬賽題解(下)


上接:藍橋杯第十一屆軟件類校內模擬賽題解(上)

編程題(四)

問題描述

小明有一塊空地,他將這塊空地划分為 \(n\)\(m\) 列的小塊,每行和每列的長度都為 \(1\)

小明選了其中的一些小塊空地,種上了草,其他小塊仍然保持是空地。

這些草長得很快,每個月,草都會向外長出一些,如果一個小塊種了草,則它將向自己的上、下、左、右四小塊空地擴展,這四小塊空地都將變為有草的小塊。

請告訴小明,\(k\) 個月后空地上哪些地方有草。

輸入格式

輸入的第一行包含兩個整數 \(n\) , \(m\)

接下來 \(n\) 行,每行包含 \(m\) 個字母,表示初始的空地狀態,字母之間沒有空格。如果為小數點,表示為空地,如果字母為 \(g\),表示種了草。

接下來包含一個整數 \(k\)

輸出格式

輸出 \(n\) 行,每行包含 \(m\) 個字母,表示 \(k\) 個月后空地的狀態。如果為小數點,表示為空地,如果字母為 \(g\),表示長了草。

評測用例規模與約定

對於 \(30\%\) 的評測用例,\(2 <= n, m <= 20\)
對於 \(70\%\) 的評測用例,\(2 <= n, m <= 100\)
對於所有評測用例,\(2 <= n, m <= 1000\)\(1 <= k <= 1000\)

——————————————————————————————

也是直接模擬草的生長情況就好了。

由於同一位置下長草時間更早的情況覆蓋了更晚的,所以我們只需考慮一塊地最先長草的狀態。

我們可以使用隊列來優化掉冗余的狀態,時間復雜度 \(O(n*m)\)

\(way\) 數組控制方向,\(f\) 數組標記一塊地是否長過草,\(dt\) 數組實時更新地圖情況。

代碼如下:

#include <bits/stdc++.h>
#define MAXN 1007
using namespace std;
struct Point { int x,y,c; };
int n,m,k,way[4][2]={{1,0},{-1,0},{0,1},{0,-1}};
char dt[MAXN][MAXN]; bool f[MAXN][MAXN];
queue<Point> Q; 
int main() {
	memset(f,0,sizeof(f));
	scanf("%d%d",&n,&m);
	for (int i=0;i<n;i++) {
		scanf("%s",dt[i]);
		for (int j=0;j<m;j++)
			if (dt[i][j]=='g')
				f[i][j]=true,Q.push((Point){i,j,0});
	}
	scanf("%d",&k);
	while(!Q.empty()) {
		Point now=Q.front(); Q.pop();
		if (now.c==k) break;
		for (int i=0;i<4;i++) {
			int tx=now.x+way[i][0],ty=now.y+way[i][1];
			if (tx<0 || tx>n || ty<0 || ty>m) continue;
			dt[tx][ty]='g';
			if (!f[tx][ty]) Q.push((Point){tx,ty,now.c+1});
		}
	}
	for (int i=0;i<n;i++) printf("%s\n",dt[i]);
	return 0;
} 

##編程題(五)

問題描述

小明想知道,滿足以下條件的正整數序列的數量:

  1. 第一項為 \(n\)
  2. 第二項不超過 \(n\)
  3. 從第三項開始,每一項小於前兩項的差的絕對值。

請計算,對於給定的 \(n\) ,有多少種滿足條件的序列。

輸入格式

輸入一行包含一個整數 \(n\)

輸出格式

輸出一個整數,表示答案。答案可能很大,請輸出答案除以 \(10000\) 的余數。

評測用例規模與約定

對於 \(20\%\) 的評測用例,\(1 <= n <= 5\)
對於 \(50\%\) 的評測用例,\(1 <= n <= 10\)
對於 \(80\%\) 的評測用例,\(1 <= n <= 100\)
對於所有評測用例,\(1 <= n <= 1000\)

——————————————————————————————

\(50\) 分的做法就是直接暴力 \(dfs\),首先敲了如下代碼,再進行優化。

#include <bits/stdc++.h>
#define MAXN 1007
using namespace std;
int ans,a[100007];
int dfs(int st) {
	ans++;
	int cha=abs(a[st]-a[st-1]);
	for (int i=1;i<cha;i++) {
		a[st+1]=i,dfs(st+1);
	}
}
int main() {
	int n;
	scanf("%d",&n),a[1]=n;
	for (int i=1;i<=n;i++) {
		a[2]=i,dfs(2);
	}
	printf("%d",ans);
	return 0;
}

發現題干一直在強調前兩項的差值,於是意識到后一項的值與其密切相關。

由於有了絕對值正數這兩個限制,前兩項具體的值都也存在影響。

用上面的程序打表觀察一下,發現連續兩項的相同的后繼項完全一致,這里可以做一個記憶化處理。

經過剪枝的 \(dfs\) 就大概可以通過 \(80\%\) 的數據了。

正解應該是 \(DP\),常數比搜索小一些,但我這里直接打表過了。

制表代碼如下:

#include <bits/stdc++.h>
#define MAXN 1007
#define mod 10000
using namespace std;
int ans,f[MAXN][MAXN];
int dfs(int p1,int p2) {
	if (f[p1][p2]) return f[p1][p2];
	f[p1][p2]=1;
	for (int i=1;i<abs(p1-p2);i++)
		f[p1][p2]+=dfs(p2,i),f[p1][p2]%=mod;
	return f[p1][p2];
}
int main() {
	freopen("","w",stdout);
	printf("int table[1001]={0,");
	for (int n=1;n<=1000;n++) {
		ans=0;
		for (int i=1;i<=n;i++)
			ans+=dfs(n,i),ans%=mod;
		printf("%d",ans);
		if (n!=1000) printf(",");
	}
	printf("}");
	return 0;
}


##編程題(六)

問題描述

小明要組織一台晚會,總共准備了 \(n\) 個節目。然后晚會的時間有限,他只能最終選擇其中的 \(m\) 個節目。

\(n\) 個節目是按照小明設想的順序給定的,順序不能改變。

小明發現,觀眾對於晚上的喜歡程度與前幾個節目的好看程度有非常大的關系,他希望選出的第一個節目盡可能好看,在此前提下希望第二個節目盡可能好看,依次類推。

小明給每個節目定義了一個好看值,請你幫助小明選擇出 \(m\) 個節目,滿足他的要求。

輸入格式

輸入的第一行包含兩個整數 \(n\) , \(m\) ,表示節目的數量和要選擇的數量。

第二行包含 \(n\) 個整數,依次為每個節目的好看值。

輸出格式

輸出一行包含 \(m\) 個整數,為選出的節目的好看值。

評測用例規模與約定

對於 \(30\%\) 的評測用例,\(1 <= n <= 20\)
對於 \(60\%\) 的評測用例,\(1 <= n <= 100\)
對於所有評測用例,\(1 <= n <= 100000\)\(0 <= value <= 100000\)

——————————————————————————————

一個貪心題。

由於在小明的策略下一定是要選擇當前能選中好看值最大的節目,所以每次選擇就是在當前能選的節目中找好看值最大的,不考慮之后如何選擇。

當然小明至少要給未選節目們留最小的選擇空間,不然就無法選夠 \(m\) 個節目,

於是發現當前能選的節目是一個區間,比如小明還有 \(p\) 個節目要選,共 \(n\) 個節目,上次選了 \(k\) 號節目。

那么他的本次選擇節目區間就是 \([k+1,n-p+1]\),如此迭代,就可以確定每次的選擇。

對於 \(60\) 分來說每次在區間內容找最大值即可,優化的話就是加入記錄了最大值和最大值來源 \(ST\) 表(我們同時關心這兩個值)。

還要注意如果區間上有多個值相等,應該保留位置靠前的一個(貪心)。

代碼如下:

#include <bits/stdc++.h>
#define MAXN 100007
using namespace std;
struct Seg { int val,id; }st[MAXN][20];
int n,m,k,v[MAXN];
inline void init() {
    for (int j=1;j<=log2(n);j++)
        for (int i=1;i<=n-(1<<j)+1;i++) {
        	if (st[i][j-1].val<st[i+(1<<(j-1))][j-1].val)
				st[i][j]=st[i+(1<<(j-1))][j-1];
			else st[i][j]=st[i][j-1];
		}
}
inline Seg q(int l,int r) {
	int t=log2(r-l+1);
	if (st[l][t].val>=st[r-(1<<t)+1][t].val) return st[l][t];
	else return st[r-(1<<t)+1][t];
}
int main() {
	scanf("%d%d",&n,&m);
	for (int i=1;i<=n;i++) scanf("%d",&st[i][0].val),st[i][0].id=i;
	init(),k=1;
	for (int i=m;i>=1;i--) {
		Seg now=q(k,n-i+1);
		k=now.id+1,printf("%d ",now.val);
	}
	return 0;
} 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM