【jzoj】2018.2.3NOIP普及组——D组模拟赛
前言
萬年D組系列…
正題
題目1:數池塘(jzoj1898)
有一個地方有一些積水,連著的積水是一個池塘,求池塘數。
輸入
第1行:由空格隔開的兩個整數:N和M
第2..N+1行:每行M個字符代表約翰農場的一排方格的狀態。每個字符或者是’W’或者是’.’,字符之間沒有空格。
輸出
第1行:約翰農場上的池塘數
樣例輸入
10 12
W……..WW.
.WWW…..WWW
….WW…WW.
………WW.
………W..
..W……W..
.W.W…..WW.
W.W.W…..W.
.W.W……W.
..W…….W.
樣例輸出
3
解題思路
深搜不解釋。
代碼
#include<cstdio> #include<iostream> using namespace std; int n,m,s; char c; bool a[101][101]; void dfs(int x,int y) {if (x<1 || y<1 || x>n || y>m || a[x][y]) return;//退出a[x][y]=true;//封dfs(x+1,y);dfs(x-1,y);dfs(x,y+1);dfs(x,y-1);dfs(x+1,y+1);dfs(x-1,y-1);dfs(x+1,y-1);dfs(x-1,y+1);//搜 } int main() {//freopen("lkcount.in","r",stdin);//freopen("lkcount.out","w",stdout);scanf("%d%d",&n,&m);for (int i=1;i<=n;i++){for (int j=1;j<=m;j++){cin>>c;//用cin輸入比較保險,昨天就是沒用cin錯了if (c=='.') a[i][j]=true;//封}}for (int i=1;i<=n;i++){for (int j=1;j<=m;j++)if (!a[i][j])//搜{dfs(i,j);s++;//累計數量}}printf("%d",s); }題目2:接蘋果(jzoj1899)
有兩顆蘋果樹,每分鐘某一顆樹會掉一顆蘋果。開始在第一顆樹下,只能移動c次的情況下在t秒最多能接到多少顆蘋果。
輸入
第1行:由空格隔開的兩個整數:T和W
第2..T+1行:1或2(每分鐘掉落蘋果的樹的編號)
輸出
第一行:在貝茜移動次數不超過W的前提下她能接到的最多蘋果數
樣例輸入
7 2
2
1
1
2
2
1
1
樣例輸出
6
解題思路
用dp,有兩種情況就是移動或不移動,這里用三維數組
f[i][j][k]表示第i分鐘,移動了j次,在第k顆樹下(其實可以不用)
代碼
#include<cstdio> #include<iostream> using namespace std; int f[1001][31][2],t,w,a[1001],maxs; int check(int t,int x)//能否接到蘋果 {if (a[t]==x) return 1;return 0; } int main() {//freopen("bcatch.in","r",stdin);//freopen("bcatch.out","w",stdout);scanf("%d%d",&t,&w);for (int i=1;i<=t;i++) scanf("%d",&a[i]);for (int i=1;i<=t;i++){f[i][0][0]=f[i-1][0][0]+check(i,1);//不移動maxs=max(maxs,f[i][0][0]);for (int j=1;j<=w;j++){f[i][j][0]=max(f[i-1][j-1][1]+check(i,2),f[i-1][j][0]+check(i,1));f[i][j][1]=max(f[i-1][j-1][0]+check(i,1),f[i-1][j][1]+check(i,2));//動態轉移maxs=max(maxs,max(f[i][j][0],f[i][j][1]));//求最大值。}}printf("%d",maxs); }題目3:找數(jzoj1416)
輸入一串序列,輸出第k大的數。
輸入
輸入文件find.in,輸入兩行,第一行兩個數N、K,N表示序列的長度,K表示要找在這個序列中的第K大的數。
第二行,N(N≤3000000)個數,用空格隔開.
輸出
輸出文件find.out,輸出序列中的第K大的數。
樣例輸入
6 3
5 2 4 3 1 6
樣例輸出
4
自解
用小根堆存K個最大的數,然后輸出堆頂
正解
c++算法庫直接sort快排
代碼
#include<cstdio> #include<algorithm> using namespace std; int n,k,a[3000001],num,x; void upA(int x)//維護堆的性質 {while (x>1 && a[x]<a[x/2]){swap(a[x],a[x/2]);x/=2;} } void downA(int x)//維護堆的性質 {int y=0;while (x*2<=num && a[x]>a[x*2] || x*2+1<=num && a[x]>a[x*2+1]){y=x*2;if (y+1<=num && a[y]>a[y+1]) y++;swap(a[x],a[y]);x=y;} } int main() {//freopen("find.in","r",stdin);//freopen("find.out","w",stdout);scanf("%d%d",&n,&k);for (int i=1;i<=n;i++) {scanf("%d",&x);//輸入if (num<k) {a[++num]=x;upA(num);}//前k個else if (x>a[1])//選大的{a[1]=x;//替換downA(1);//維護}}printf("%d",a[1]);//輸出 }題目4:最短路徑(jzoj1417)
沒錯這道題就像題目一樣,沒錯,就是遞推(才不是什么最短路)。一個n*m的地方,不能走斜線,求最短數量。
輸入
輸入文件Sline.in,一行,兩個數M,N,其中 2
輸出
輸出文件sline.out,輸出最短路的走法總數.
樣例輸入
7 5
樣例輸出
210
解題思路
首先,我們可以從左邊或下面來,所以f[i][j]=f[i-1]+f[j-1]。然后因為數據忒大,有不需要取膜,又容易超時。
所以這道題的方法是:禁忌·壓位高精滾動反復遞推
代碼
#include<cstdio> using namespace std; int n,m,f[2][801]; int a[1601][61]; void add(int n1,int n2,int n3) {int g=0;for (int i=1;i<=60;i++){a[n1][i]=a[n1][i]+a[n2][i]+g;g=a[n1][i]/100000000;a[n1][i]%=100000000;a[n3][i]=a[n1][i];} } void write(int n1) {int w=60;while (a[n1][w]==0) w--;//找printf("%d",a[n1][w]);//輸出for (int i=w-1;i>=1;i--){if (a[n1][i]<10000000) printf("0");//暴力判斷前導0if (a[n1][i]<1000000) printf("0");if (a[n1][i]<100000) printf("0");if (a[n1][i]<10000) printf("0");if (a[n1][i]<1000) printf("0");if (a[n1][i]<100) printf("0");if (a[n1][i]<10) printf("0");printf("%d",a[n1][i]);} } int main() {//freopen("sline.in","r",stdin);//freopen("sline.out","w",stdout);scanf("%d%d",&n,&m);if (m>n) {int t=m;m=n;n=t;}//避免錯誤for (int i=1;i<=m;i++) {f[0][i]=i;f[1][i]=n+i;}//對應高精度數組號a[f[1][1]][1]=1;//初值for (int i=1;i<=n;i++){for (int j=1;j<=m;j++){if (i!=1 || j!=1)add(f[(i-1)%2][j],f[i%2][j-1],f[i%2][j]);//加}}write(f[n%2][m]); }題目5:棋盤覆蓋(jzoj1418)
一個N*N的棋盤,用“L”字方塊(覆蓋3格)覆蓋除了特殊方塊棋盤(不能重疊)。求覆蓋方法。
輸入
輸入文件Chessboard.in,共兩行,第一行一個數N為棋盤的大小,N滿足條件N=2^K,1<=K<=10.
第二行,兩個數x,y,表示棋盤中那一個與其它方格不同的位置,x表示行,y表示列.
輸出
輸出文件Chessboard.out,輸出N行N列,共N×N個數,表示用L 型(占3 個小格)紙片覆蓋棋盤上除特殊方格的所有部分,各紙片不得重疊的方法.其中的數表示L型紙片覆蓋的順序編號, 不同的L型紙片用不同的編號,同一個L型紙片占據的三個位置相同,編號從1開始,特殊方格用-1標志;每兩個數之間用一個空格隔開,每行最末一個數后面沒有空格.
樣例輸入
4
2 2
樣例輸出
2 2 3 3
2 -1 1 3
4 1 1 5
4 4 5 5
解題思路
用分治算法,不斷分,然后計算子問題。
代碼
#include<cstdio> using namespace std; int number,dx,dy,n,a[1025][1025]; void dfs(int x,int y,int ux,int uy,int s)//x,y表示位置,ux,uy表示特殊符號位置,s表示邊長 {if (s==1) return;//退出number++;//號int zx=x+s/2;int zy=y+s/2;//中間位置if (ux<zx && uy<zy)//特殊格子在左上{a[zx-1][zy]=number;a[zx][zy-1]=number;a[zx][zy]=number;//記錄dfs(x,y,ux,uy,s/2);//分治dfs(zx,y,zx,zy-1,s/2);dfs(x,zy,zx-1,zy,s/2);dfs(zx,zy,zx,zy,s/2);}else if (ux<zx && uy>=zy){a[zx][zy-1]=number;a[zx-1][zy-1]=number;a[zx][zy]=number;dfs(x,y,zx-1,zy-1,s/2);dfs(x,zy,ux,uy,s/2);dfs(zx,y,zx,zy-1,s/2);dfs(zx,zy,zx,zy,s/2);}else if (ux>=zx && uy<zy){a[zx-1][zy-1]=number;a[zx-1][zy]=number;a[zx][zy]=number;dfs(x,y,zx-1,zy-1,s/2);dfs(zx,y,ux,uy,s/2);dfs(x,zy,zx-1,zy,s/2);dfs(zx,zy,zx,zy,s/2);}else if (ux>=zx && uy>=zy){a[zx-1][zy]=number;a[zx][zy-1]=number;a[zx-1][zy-1]=number;dfs(x,y,zx-1,zy-1,s/2);dfs(x,zy,zx-1,zy,s/2);dfs(zx,y,zx,zy-1,s/2);dfs(zx,zy,ux,uy,s/2);} } int main() {//freopen("chessboard.in","r",stdin);//freopen("chessboard.out","w",stdout);scanf("%d%d%d",&n,&dx,&dy);a[dx][dy]=-1;//特殊方塊dfs(1,1,dx,dy,n);//搜索for (int i=1;i<=n;i++){for (int j=1;j<=n;j++)printf("%d ",a[i][j]);printf("\n");}//輸出 }總結
以上是生活随笔為你收集整理的【jzoj】2018.2.3NOIP普及组——D组模拟赛的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 如虎添翼的意思是什么 如虎添翼的意思简述
- 下一篇: 相差700值不值,不完全的小米8/小米8