1. 程式人生 > >洛谷——基礎搜索

洛谷——基礎搜索

不重復 這樣的 中間 出現 ios max map ear name

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;
}

自己選的路,跪著也要走完!!!

洛谷——基礎搜索