洛谷——基礎搜索
1.P1706 全排列問題
題目描述
輸出自然數1到n所有不重復的排列,即n的全排列,要求所產生的任一數字序列中不允許出現重復的數字。
輸入輸出格式
輸入格式:
n(1≤n≤9)
輸出格式:
由1~n組成的所有不重復的數字序列,每行一個序列。每個數字保留5個常寬。
輸入輸出樣例
輸入樣例#1:3輸出樣例#1:
1 2 3 1 3 2 2 1 3 2 3 1 3 1 2 3 2 1
(⊙v⊙)嗯~ 代碼:
#include<iostream> #include<cstdio> #include<iomanip> using namespace std; int n,num[1001],vis[1001]; void print(int n){ for(int i=1; i<=n; i++){ cout<<setw(5)<<num[i]; }printf("\n"); } void search(int s) { for(int i=1; i<=n; i++) { if(!vis[i]) { num[s]= i; vis[i] = 1; if(s==n) print(s); else search(s+1); vis[i] = 0; } } } int main() { scanf("%d",&n); search(1); return 0; }
2.P1531 I Hate It
題目背景
很多學校流行一種比較的習慣。老師們很喜歡詢問,從某某到某某當中,分數最高的是多少。這讓很多學生很反感。
題目描述
不管你喜不喜歡,現在需要你做的是,就是按照老師的要求,寫一個程序,模擬老師的詢問。當然,老師有時候需要更新某位同學的成績
輸入輸出格式
輸入格式:
第一行,有兩個正整數 N 和 M ( 0<N<=200000,0<M<5000 ),分別代表學生的數目和操作的數目。學生ID編號分別從1編到N。第二行包含N個整數,代表這N個學生的初始成績,其中第i個數代表ID為i的學生的成績。接下來有M行。每一行有一個字符 C (只取‘Q‘或‘U‘) ,和兩個正整數A,B。當C為‘Q‘的時候,表示這是一條詢問操作,它詢問ID從A到B(包括A,B)的學生當中,成績最高的是多少。當C為‘U‘的時候,表示這是一條更新操作,如果當前A學生的成績低於B,則把ID為A的學生的成績更改為B,否則不改動。
輸出格式:
對於每一次詢問操作,在一行裏面輸出最高成績
輸入輸出樣例
輸入樣例#1:5 6 1 2 3 4 5 Q 1 5 U 3 6 Q 3 4 Q 4 5 U 2 9 Q 1 5輸出樣例#1: 5
6 5 9
思路:
類似於線段樹
建樹:要將父節點的值附為左孩子和右孩子的最大值,(便於詢問區間的時候直接返回最大值)
詢問:如果不在區間內,無意義,在區間內的返回最大值(也就是此節點的值),超出區間繼續詢問其子節點
修改:根據題意,要在當前節點的值與B中取大,如果在區間內,就取大,否則return,繼續修改子節點
(⊙v⊙)嗯~ 代碼:
#include<iostream> #include<cstdio> using namespace std; const int N = 200005; const int INF = 1<<30; int n,m,l,r,ans; char sty; struct Tree{ int l,r,w; }tree[5*N]; void build(int k,int ll,int rr){ tree[k].l=ll,tree[k].r=rr; if(ll==rr) { scanf("%d",&tree[k].w); return ; } int mid=(ll+rr)/2; build(k*2,ll,mid); build(k*2+1,mid+1,rr); tree[k].w = max(tree[k*2].w , tree[k*2+1].w); } int ask(int k,int ll,int rr) { if(tree[k].r<ll||tree[k].l>rr) return -0x7fffffff; if(tree[k].l>=ll&&tree[k].r<=rr) return tree[k].w; return max(ask(k*2,ll,rr),ask(k*2+1,ll,rr)); } void change(int k,int ll,int rr) { if(ll>=tree[k].l&&ll<=tree[k].r) tree[k].w = max(tree[k].w,rr); else return; change(k*2,ll,rr); change(k*2+1,ll,rr); } int main() { scanf("%d%d",&n,&m); build(1,1,n); for(int i=1; i<=m; i++) { cin>>sty>>l>>r; if(sty==‘Q‘) { printf("%d\n",ask(1,l,r)); } if(sty==‘U‘) { change(1,l,r); } } return 0; }
3.P1162 填塗顏色
題目描述
由數字0 組成的方陣中,有一任意形狀閉合圈,閉合圈由數字1構成,圍圈時只走上下左右4個方向。現要求把閉合圈內的所有空間都填寫成2.例如:6X6的方陣(n=6),塗色前和塗色後的方陣如下:
0 0 0 0 0 0 0 0 0 0 0 0
0 0 1 1 1 1 0 0 1 1 1 1
0 1 1 0 0 1 0 1 1 2 2 1
1 1 0 0 0 1 1 1 2 2 2 1
1 0 0 0 0 1 1 2 2 2 2 1
1 1 1 1 1 1 1 1 1 1 1 1
輸入輸出格式
輸入格式:
每組測試數據第一行一個整數:n。其中n(1<=n<=30)
接下來n行,由0和1組成的nXn的方陣。
方陣內只有一個閉合圈,圈內至少有一個0。
//感謝黃小U飲品指出本題數據和數據格式不一樣. 已修改(輸入格式)
輸出格式:
已經填好數字2的完整方陣。
輸入輸出樣例
輸入樣例#1:6 0 0 0 0 0 0 0 0 1 1 1 1 0 1 1 0 0 1 1 1 0 0 0 1 1 0 0 0 0 1 1 1 1 1 1 1輸出樣例#1:
0 0 0 0 0 0 0 0 1 1 1 1 0 1 1 2 2 1 1 1 2 2 2 1 1 2 2 2 2 1 1 1 1 1 1 1
說明
1<=n<=30
思路:
分別從四個角開始搜索,只搜索0,將能搜索到的0全都標記為3(不為0,1,2就行),則能搜到就為輸出的0,仍然為0的就輸出為2,
1不改變,輸出。
^_^ 代碼:
#include<queue> #include<cstdio> #include<iostream> using namespace std; int n,map[32][32]; int mh[5]= {0,1,0,-1,0}, ml[5]= {0,0,1,0,-1}; struct node { int h,l; } now,nex; queue<node>car; void bfs(int h,int l) { now.h=h,now.l=l; map[h][l]=3; car.push(now); int hh,ll; while(!car.empty()) { now=car.front(); for(int i=1; i<=4; ++i) { hh=now.h+mh[i],ll=now.l+ml[i]; if(hh>=1&&hh<=n&&ll>=1&&ll<=n&&map[hh][ll]==0) { map[hh][ll]=3; nex.h=hh,nex.l=ll; car.push(nex); } } car.pop(); } } int main() { scanf("%d",&n); for(int i=1; i<=n; ++i) for(int j=1; j<=n; ++j) scanf("%d",&map[i][j]); for(int i=1; i<=n; ++i){ if(!map[i][1]) bfs(i,1); if(!map[i][n]) bfs(i,n); if(!map[1][i]) bfs(1,i); if(!map[n][i]) bfs(n,i); } for(int i=1; i<=n; ++i) { for(int j=1; j<=n; ++j) { if(map[i][j]==3) cout<<0<<" "; else if(map[i][j]==0) cout<<2<<" "; else cout<<1<<" "; } cout<<endl; } return 0; }
4.P1451 求細胞數量
題目描述
一矩形陣列由數字0到9組成,數字1到9代表細胞,細胞的定義為沿細胞數字上下左右若還是細胞數字則為同一細胞,求給定矩形陣列的細胞個數。(1<=m,n<=100)?
輸入輸出格式
輸入格式:
輸入:整數m,n(m行,n列)
矩陣
輸出格式:
輸出:細胞的個數
輸入輸出樣例
輸入樣例#1:4 10 0234500067 1034560500 2045600671 0000000089輸出樣例#1:
4
思路:
註意輸入輸出,(可以用標準庫queue)。
↖(^ω^)↗ 代碼:
#include<iostream> #include<cstdio> using namespace std; int n,m,vis[101][101],xbb[101][101],q[101][3],num; int dx[4]={-1,0,1,0}; int dy[4]={0,1,0,-1}; char xb[101]; void bfs(int x,int y) { int head=0,tail=1; q[1][1]=x,q[1][2]=y; num++;xbb[x][y]=0; do{ head++; for(int i=0; i<=3; i++) { int xx=q[head][1]+dx[i],yy=q[head][2]+dy[i]; if(xx>=0&&xx<n&&yy>=0&&yy<m&&xbb[xx][yy]) { tail++; q[tail][1]=xx; q[tail][2]=yy; xbb[xx][yy]=0; } } }while(head<tail); } int main() { cin>>n>>m; for(int i=0; i<n; i++) for(int j=0; j<m; j++) xbb[i][j]=1;
for(int i=0; i<n; i++) { cin>>xb; for(int j=0; j<m ;j++) if(xb[j]==‘0‘) xbb[i][j]=0; } for(int i=0; i<n; i++) { for(int j=0; j<m ;j++) { if(xbb[i][j]) bfs(i,j); } } cout<<num<<endl; return 0; }
5.P1657 選書
題目描述
學校放寒假時,信息學奧賽輔導老師有1,2,3……x本書,要分給參加培訓的x個人,每人只能選一本書,但是每人有兩本喜歡的書。老師事先讓每個人將自己喜歡的書填寫在一張表上。然後根據他們填寫的表來分配書本,希望設計一個程序幫助老師求出所有可能的分配方案,使每個學生都滿意。
輸入輸出格式
輸入格式:
第1行:一個數x
第2行~第1+x行:每行兩個數,表示ai喜歡的書的序號
輸出格式:
只有一個數:總方案數total。
輸入輸出樣例
輸入樣例#1:5 1 3 4 5 2 5 1 4 3 5輸出樣例#1:
2
說明
所有數據:x<=20
(世界上最難出數據的題目,沒有之一……)
O(∩_∩)O~ 代碼:
#include<iostream> #include<cstdio> using namespace std; int ans,n,love1,love2,like[21][21]; int choose[21]; void dfs(int n,int k){ for(int i=1; i<=n;i++) { if(!choose[i]&&like[k][i]) { choose[i]=1; if(k==n) ans++; else dfs(n,k+1); choose[i]=0; } } } int main() { cin>>n; for(int i=1; i<=n; i++) { cin>>love1>>love2; like[i][love1]=1; like[i][love2]=1; } dfs(n,1); cout<<ans<<endl; return 0; }
6.P2040 打開所有的燈
題目背景
pmshz在玩一個益(ruo)智(zhi)的小遊戲,目的是打開九盞燈所有的燈,這樣的遊戲難倒了pmshz。。。
題目描述
這個燈很奇(fan)怪(ren),點一下就會將這個燈和其周圍四盞燈的開關狀態全部改變。現在你的任務就是就是告訴pmshz要全部打開這些燈。
例如
0 1 1
1 0 0
1 0 1
點一下最中間的燈【2,2】就變成了
0 0 1
0 1 1
1 1 1
再點一下左上角的燈【1,1】就變成了
1 1 1
1 1 1
1 1 1
達成目標。最少需要2步。
輸出2即可。
輸入輸出格式
輸入格式:
九個數字,3*3的格式輸入,每兩個數字中間只有一個空格,表示燈初始的開關狀態。(0表示關,1表示開)
輸出格式:
1個整數,表示最少打開所有燈所需要的步數。
輸入輸出樣例
輸入樣例#1:0 1 1 1 0 0 1 0 1輸出樣例#1:
2
說明
這個題水不水,就看你怎麽考慮了。。。。
(づ ̄3 ̄)づ╭?~ 代碼:
#include<iostream> #include<cstdio> using namespace std; int light[5][5],ans=10; int vis[5][5]; bool choose(){ for(int i=1; i<=3; i++) for(int j=1; j<=3; j++) if(!light[i][j]) return 0; return 1; } void dfs(int k){ if(k==10) return ; for(int i=1; i<=3; i++) { for(int j=1; j<=3; j++) { if(!vis[i][j]) { vis[i][j]=1; light[i][j]=!light[i][j]; light[i+1][j]=!light[i+1][j]; light[i-1][j]=!light[i-1][j]; light[i][j+1]=!light[i][j+1]; light[i][j-1]=!light[i][j-1]; if(choose()) ans=min(ans,k); dfs(k+1); vis[i][j]=0; light[i][j]=!light[i][j]; light[i+1][j]=!light[i+1][j]; light[i-1][j]=!light[i-1][j]; light[i][j+1]=!light[i][j+1]; light[i][j-1]=!light[i][j-1]; } } } } int main() { for(int i=1; i<=3; i++) { for(int j=1; j<=3; j++) { cin>>light[i][j]; } } if(choose()) ans=0; dfs(1); cout<<ans<<endl; return 0; }
自己選的路,跪著也要走完!!!
洛谷——基礎搜索