2021 年百度之星·程序设计大赛 - 初赛三(部分)
- 數字游戲
- 網格路徑
- 蟲族基地
- 環上游走
鏈接
數字游戲
Accepts: 7247 Submissions: 13194
Time Limit: 2000/1000 MS (Java/Others)
Memory Limit: 32768/32768 K (Java/Others)
Problem Description
小蝸蝸有 nnn 個數字(實數),但他不知道這些數字具體是啥。
他只知道這 nnn 個數字的最大值、最小值和平均值,但也不一定是對的。
現在,小蝸蝸想知道,存不存在一種方案,使得這 nn 個數字的最大值、最小值和平均值恰好等于給定值。
Input
第一行讀入一個整數 test(1≤test≤100000)test(1\leq test \leq 100000)test(1≤test≤100000) 表示數據組數。
接下來 testtesttest 行,每行四個整數 n,max,min,ave(1≤n≤100000,?100≤max,min,ave≤100)n, max, min, ave(1 \leq n \leq 100000, -100 \leq max, min, ave \leq 100)n,max,min,ave(1≤n≤100000,?100≤max,min,ave≤100) 分別表示最大值、最小值和平均值。
注意,一開始的 nnn 個數字的取值范圍是實數。
Output
輸出共 testtesttest 行。
對于第 iii 行,如果存在一組合法方案,輸出 yes,否則輸出 no。
Sample Input
2 3 1 1 1 2 3 1 1Sample Output
yes no思路
首先特判 n==1n==1n==1 的情況,對于其他情況,計算 nnn 個數之和的最大值 (n?1)×max+min(n-1)\times max+min(n?1)×max+min,最小值 (n?1)×min+max(n-1)\times min+max(n?1)×min+max,若 avg×navg\times navg×n 在二者之間,則符合要求,否則不符合。
比較坑的是,輸入的 maxmaxmax 未必比 minminmin 大,所以需要判斷 max≥avg≥minmax \geq avg\geq minmax≥avg≥min,若不滿足這一條件,直接輸出no。
#include<bits/stdc++.h> #define int long long using namespace std; int T,n,mx,mn,avg;void solve(){int mnn,mxn;cin>>n>>mx>>mn>>avg;if(mx>=mn&&avg<=mx&&avg>=mn){if(n==1){if(mx==mn&&mn==avg){ cout<<"yes\n"; return; }else{ cout<<"no\n"; return; }}mnn=mxn=mx+mn;avg*=n;if(n-2>0) mxn+=(n-2)*mx;if(n-2>0) mnn+=(n-2)*mn;if(avg>=mnn&&avg<=mxn) cout<<"yes\n";else cout<<"no\n";}else{cout<<"no\n";} }signed main(){ios::sync_with_stdio(false);for(cin>>T;T;T--) solve(); }網格路徑
Accepts: 735 Submissions: 3776
Time Limit: 2000/1000 MS (Java/Others)
Memory Limit: 32768/32768 K (Java/Others)
Problem Description
給定一張 n×nn\times nn×n 的網格圖,有些格子能走,有些格子不能走,左上角的格子坐標為 (1,1)(1,1)(1,1),右下角的格子坐標為 (n,n)(n,n)(n,n)。
問最多可以找到多少條從 (1,1)(1,1)(1,1) 到 (n,n)(n,n)(n,n) 的不相交路徑,使得每條路徑經過的每個格子(包含 (1,1)(1, 1)(1,1) 和 (n,n)(n, n)(n,n))都是能走的格子?
每次我們只可以向右或向下走,不能離開網格圖的邊界。兩條路徑不相交當且僅當除了格子 (1,1)(1,1)(1,1) 和 (n,n)(n,n)(n,n),它們沒有任何公共部分。
Input
第一行一個整數 test(1≤test≤1000)test(1\leq test \leq 1000)test(1≤test≤1000) 表示數據組數。
對于每組數據,第一行一個整數 n(2≤n≤10)n(2\leq n \leq 10)n(2≤n≤10) 表示網格圖的大小。
接下來 nnn 行,每行一個長度為 nnn 的字符串。第 iii 行第 jjj 列的字符 ‘.’ 表示 (i,j)(i,j)(i,j) 可以走,’#’ 表示不能走。
Output
對于每組數據,輸出一行一個整數表示最多可以找到的不相交路徑數目。
Sample Input
3 2 .. .. 3 ... .## ... 3 .#. #.. ...Sample Output
2 1 0思路
最多有兩條路徑,所以主要是判斷答案為 111 還是為 222 。
可以用深搜找出一條盡量靠右的路,把走過的路標記為已訪問。在走一條盡量靠下的路。
特判 mp[1][1]mp[1][1]mp[1][1] 和 mp[n][n]mp[n][n]mp[n][n] ,若它們不能走,則答案直接為 000 。
#include<bits/stdc++.h> using namespace std; const int rdir[2][2]={{0,1},{1,0}}; const int ldir[2][2]={{1,0},{0,1}}; int T,n,vis[20][20]; char mp[20][20];bool dfs(int x,int y,int flag){vis[x][y]=1; for(int k=0;k<2;k++){int xx,yy;if(flag) xx=x+rdir[k][0],yy=y+rdir[k][1];else xx=x+ldir[k][0],yy=y+ldir[k][1];if(xx==n&&yy==n) return true;if(xx<=n&&y<=n&&x>0&&y>0&&mp[xx][yy]=='.'&&vis[xx][yy]==0){vis[xx][yy]=1; if(dfs(xx,yy,flag)) return true;}}return false; }void solve(){int ans=0;scanf("%d",&n);memset(vis,0,sizeof(vis));for(int i=1;i<=n;i++) scanf("%s",mp[i]+1);if(mp[1][1]=='#'||mp[n][n]=='#'){ printf("0\n"); return; }if(dfs(1,1,1)) ans++;if(dfs(1,1,0)) ans++;printf("%d\n",ans); }int main(){for(scanf("%d",&T);T;T--) solve(); }蟲族基地
Accepts: 195 Submissions: 1613
Time Limit: 2000/1000 MS (Java/Others)
Memory Limit: 32768/32768 K (Java/Others)
Problem Description
有一個 n×mn \times mn×m 的網格,左上角的格子坐標為 (1,1)(1,1)(1,1),右下角的格子坐標為 (n,m)(n,m)(n,m)。
初始的時候,網格上有兩個蟲族基地,其中一個在第一行,另一個在最后一行。 對于每個蟲族基地,在第 i2i^2i2 秒結束的時候,與蟲族基地曼哈頓距離為 iii 的格子會被蟲族占領。
有一批物資要從 (1,1)(1,1)(1,1) 運送到 (n,m)(n,m)(n,m),每次我們可以走上下左右四個方向,我們不能離開網格圖的邊界。
物資經過的路徑(包含起終點)不能存在任何被蟲族占領的格子(蟲族基地也不行)。
請問第幾秒結束時,從 (1,1)(1,1)(1,1) 到 (n,m)(n,m)(n,m) 的聯系會被切斷?(不存在一條從左上到右下的路徑)
Input
第一行一個正整數 test(1≤test≤100000)test(1 \le test \le 100000)test(1≤test≤100000) 表示數據組數。
對于每組數據,一行四個整數 n,m,x1,x2(1≤n,m≤1000000000,1≤x1,x2≤m)n, m, x_1, x_2(1\le n,m\le 1000000000, 1\le x_1, x_2 \le m)n,m,x1?,x2?(1≤n,m≤1000000000,1≤x1?,x2?≤m)。兩個蟲族基地的坐標分別為 (1,x1)(1, x_1)(1,x1?) 和 (n,x2)(n, x_2)(n,x2?)。
Output
對于每組數據,輸出一行一個整數表示答案。
Sample Input
3 2 2 2 1 3 3 3 1 3 3 1 1Sample Output
0 1 0思路
不斷更新道路被切斷時間的最小值 mnmnmn 。首先,若是起點 (1,1)(1,1)(1,1) 或是終點 (n,n)(n,n)(n,n) 被占領,則被切斷;若是蟻群縱向從 111 占領到 nnn,那么也被切斷;計算兩個蟻群之間的曼哈頓距離 mhdLenmhdLenmhdLen ,若是兩個蟻群的橫坐標相同,那么用 mhdLen2\frac {mhdLen} 22mhdLen? 更新最小值,否則,用 mhdLen?12\frac{mhdLen-1}{2}2mhdLen?1? 更新最小值。
最后特判一下最小值會不會小于 000,若小于 000,則置零。輸出 mn2mn^2mn2
環上游走
Accepts: 535 Submissions: 1166
Time Limit: 2000/1000 MS (Java/Others)
Memory Limit: 32768/32768 K (Java/Others)
Problem Description
有一個環,環上有 nnn 個位置,它們的編號為 1...n1...n1...n。
位置 i(1<i<n)i(1 < i < n)i(1<i<n) 左右兩邊分別是位置 i?1i-1i?1 和位置 i+1i+1i+1,位置 111 左右兩邊分別是位置 nnn 和位置 222,位置 nnn 左右兩邊分別是位置 n?1n-1n?1 和位置 111。
現在,我們要玩一個游戲。初始我們在位置 111,游戲共 n?1n-1n?1 輪,對于第 i(1≤i<n)i(1 \le i < n)i(1≤i<n) 輪,我們可以選擇從當前位置往左或往右連續走 iii 個位置。
現在我們想知道,對于給定的 nnn,有多少種方案,使得我們停留的 nnn 個位置(初始的位置 111 和 n?1n-1n?1 輪中每一輪結束時候的位置)沒有重復。
Input
第一行一個整數 test(1≤test≤80)test(1 \le test \le 80)test(1≤test≤80) 表示數據組數。
對于每組數據,一行一個整數 n(1≤n≤80)n(1 \le n \le 80)n(1≤n≤80) 表示環的大小。
Output
對于每組數據,一行一個整數表示答案。
Sample Input
4 2 3 4 5Sample Output
2 2 4 2思路
這題先是深搜交一發,超時了,就打個表,過了。
不過也有別人寫的深搜就過了,但是賽后同樣的代碼再交一次,還會超時。可能是比賽時的測評機有優化。
//深搜超時代碼 #include<bits/stdc++.h> using namespace std; int T,n,ans; bitset<80> b;void dfs(int p,int step){if(step==n) return void(ans++);int np=p+step; if(np>n) np-=n;if(b[np]==0){ b[np]=1; dfs(np,step+1); b[np]=0; } np=p-step+n; if(np>n) np-=n;if(b[np]==0){ b[np]=1; dfs(np,step+1); b[np]=0; } }void solve(){ans=0; cin>>n;b[1]=1,dfs(1,1);cout<<ans<<endl; }int main(){ios::sync_with_stdio(false);for(cin>>T;T;T--) solve(); } #include<bits/stdc++.h> using namespace std; int T,n,a[100]={0,1,2,2,4,2,4,4,8,2,4,6,8,2,8,6,16,2,4,6,8,4,12,6,16,4,4,4,16,2,12,10,32,4,4,8,8,2,12,6,16,2,8,6,24,6,12,8,32,6,8,6,8,2,8,10,32,4,4,6,24,2,20,6,64,6,8,8,8,4,16,6,16,2,4,8,24,14,12,6,32};int main(){scanf("%d",&T);while(T--){scanf("%d",&n);printf("%d\n",a[n]);} }總結
以上是生活随笔為你收集整理的2021 年百度之星·程序设计大赛 - 初赛三(部分)的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 实用干货秘籍!最经典的10个Pandas
- 下一篇: “约见”面试官系列之常见面试题之第五十二