洛谷【算法1-7】搜索

P1219 [USACO1.5] 八皇后 Checker Challenge - 洛谷 | 计算机科学教育新生态 (luogu.com.cn)

复制代码
#include<iostream>
using namespace std;
int n,m1[30],m2[30],m3[30],ans[15],res=0;
void setvalue(int step,int j,int k){
    ans[step]=j;
    m1[j]=k;
    m2[j+step]=k;
    m3[step-j+n]=k;
}
void dfs(int step){
    if(step>n){
        res++;
        if(res<=3){
            for(int i=1;i<=n;i++) cout<<ans[i]<<" ";
            cout<<endl;
        }
        return;
    }
    for(int j=1;j<=n;j++){
        if(m1[j] || m2[step+j] || m3[step-j+n]) continue;
        setvalue(step,j,1);
        dfs(step+1);
        setvalue(step,j,0);
    }
}
signed main(){
    ios::sync_with_stdio(false);
    cin.tie(0);cout.tie(0);
    cin>>n;
    dfs(1);
    cout<<res<<endl;
    
    return 0;
}
复制代码

P2392 kkksc03考前临时抱佛脚 - 洛谷 | 计算机科学教育新生态 (luogu.com.cn)

复制代码
#include<iostream>
#include<algorithm>
#include<cstring>
using namespace std;
const int INF=0x3f3f3f3f;
int l,r,ans=0,minn,s[5],a[5][20];
void DFS(int pos,int subject){
    if(pos>s[subject]){
        minn=min(minn,max(l,r));
        return ;
    }
    l+=a[subject][pos];
    DFS(pos+1,subject);
    l-=a[subject][pos];
    r+=a[subject][pos];
    DFS(pos+1,subject);
    r-=a[subject][pos];
}
signed main(){
    ios::sync_with_stdio(false);
    cin.tie(0);cout.tie(0);
    cin>>s[1]>>s[2]>>s[3]>>s[4];
    for(int i=1;i<=4;i++){
        l=r=0;
        minn=INF;
        for(int j=1;j<=s[i];j++) cin>>a[i][j];
        DFS(1,i);
        ans+=minn;
    }
    cout<<ans<<endl;
    return 0;
}
复制代码

P1443 马的遍历 - 洛谷 | 计算机科学教育新生态 (luogu.com.cn)

复制代码
#include<iostream> 
#include<queue>
#include<cstring>
using namespace std;
const int INF=0x3f3f3f3f;
const int N=410;
int n,m,x,y,vis[N][N],s[N][N];
struct node{
    int dx,dy,step;
};
#define check(a,b) (a>=1&&a<=n&&b>=1&&b<=m)
void BFS(){
    node begin,next;
    begin.dx=x;
    begin.dy=y;
    begin.step=0;
    vis[begin.dx][begin.dy]=-INF;
    queue<node> q;
    q.push(begin);
    while(!q.empty()){
        begin=q.front();
        q.pop();
        int nx,ny;
        nx=begin.dx-1;
        ny=begin.dy+2;
        if(check(nx,ny)&&!vis[nx][ny]){
            next.dx=nx;
            next.dy=ny;
            next.step=begin.step+1;
            vis[nx][ny]=next.step;
            q.push(next);
        }
        nx=begin.dx-1;
        ny=begin.dy-2;
        if(check(nx,ny)&&!vis[nx][ny]){
            next.dx=nx;
            next.dy=ny;
            next.step=begin.step+1;
            vis[nx][ny]=next.step;
            q.push(next);
        }
        nx=begin.dx-2;
        ny=begin.dy+1;
        if(check(nx,ny)&&!vis[nx][ny]){
            next.dx=nx;
            next.dy=ny;
            next.step=begin.step+1;
            vis[nx][ny]=next.step;
            q.push(next);
        }
        nx=begin.dx-2;
        ny=begin.dy-1;
        if(check(nx,ny)&&!vis[nx][ny]){
            next.dx=nx;
            next.dy=ny;
            next.step=begin.step+1;
            vis[nx][ny]=next.step;
            q.push(next);
        }
        nx=begin.dx+1;
        ny=begin.dy+2;
        if(check(nx,ny)&&!vis[nx][ny]){
            next.dx=nx;
            next.dy=ny;
            next.step=begin.step+1;
            vis[nx][ny]=next.step;
            q.push(next);
        }
        nx=begin.dx+1;
        ny=begin.dy-2;
        if(check(nx,ny)&&!vis[nx][ny]){
            next.dx=nx;
            next.dy=ny;
            next.step=begin.step+1;
            vis[nx][ny]=next.step;
            q.push(next);
        }
        nx=begin.dx+2;
        ny=begin.dy+1;
        if(check(nx,ny)&&!vis[nx][ny]){
            next.dx=nx;
            next.dy=ny;
            next.step=begin.step+1;
            vis[nx][ny]=next.step;
            q.push(next);
        }
        nx=begin.dx+2;
        ny=begin.dy-1;
        if(check(nx,ny)&&!vis[nx][ny]){
            next.dx=nx;
            next.dy=ny;
            next.step=begin.step+1;
            vis[nx][ny]=next.step;
            q.push(next);
        }
    }
    for(int i=1;i<=n;i++){
        for(int j=1;j<=m;j++){
            if(vis[i][j]==0){
                vis[i][j]=-1;
            }
        }
    }
    vis[x][y]=0;
}
signed main(){
    ios::sync_with_stdio(false);
    cin.tie(0);cout.tie(0);
    cin>>n>>m>>x>>y;
    memset(vis,0,sizeof(vis));
    BFS();
    for(int i=1;i<=n;i++){
        for(int j=1;j<=m;j++){
            cout<<vis[i][j]<<"    ";
        }
        cout<<endl;
    }
    return 0;
}
复制代码

P1135 奇怪的电梯 - 洛谷 | 计算机科学教育新生态 (luogu.com.cn)

复制代码
#include<iostream> 
#include<queue>
#include<cstring>
using namespace std;
const int N=210;
int K[N],n,A,B,vis[N];
struct node{
    int now,step;
};
#define check(a) (a>=1&&a<=n)
void BFS(){
    node begin,next;
    begin.now=A;
    begin.step=0;
    vis[begin.now]=1;
    queue<node> q;
    q.push(begin);
    while(!q.empty()){
        begin=q.front();
        q.pop();
        if(begin.now==B){
            cout<<begin.step<<endl;
            return ;
        }
        int c;
        c=begin.now+K[begin.now];
        if(check(c)&&!vis[c]){
            vis[c]=1;
            next.now=c;
            next.step=begin.step+1;
            q.push(next);
        }
        c=begin.now-K[begin.now];
        if(check(c)&&!vis[c]){
            vis[c]=1;
            next.now=c;
            next.step=begin.step+1;
            q.push(next);
        }
    }
    cout<<"-1"<<endl;
}
signed main(){
    ios::sync_with_stdio(false);
    cin.tie(0);cout.tie(0);
    cin>>n>>A>>B;
    for(int i=1;i<=n;i++) cin>>K[i];
    memset(vis,0,sizeof(vis));
    BFS();
    
    return 0;
}
复制代码

P2895 [USACO08FEB] Meteor Shower S - 洛谷 | 计算机科学教育新生态 (luogu.com.cn)

复制代码
#include<iostream>
#include<queue>
#include<cstring>
using namespace std;
const int INF=0x3f3f3f3f;  
int M,map[400][400],mx,my,mt,ans[400][400];
int dir[5][2]={{1,0},{-1,0},{0,1},{0,-1},{0,0}};
bool vis[400][400];
struct node{
    int x,y;
};
#define check(a,b) (a>=0&&b>=0)
int ch(int a){
    if(a==-1) return INF;
    else return a;
}
void BFS(){
    node begin,next;
    begin.x=0;
    begin.y=0;
    queue<node> q;
    q.push(begin);
    while(!q.empty()){
        begin=q.front();
        q.pop();
        if(map[begin.x][begin.y]==-1){
            cout<<ans[begin.x][begin.y]<<endl;
            return ;
        }
        int res=ans[begin.x][begin.y]+1;
        for(int i=0;i<4;i++){
            int nx=begin.x+dir[i][0];
            int ny=begin.y+dir[i][1];
            if(check(nx,ny) && res<ch(map[nx][ny]) && !vis[nx][ny]){
                vis[nx][ny]=1;
                next.x=nx;
                next.y=ny;
                q.push(next);
                ans[nx][ny]=res;
            }
        }
    }
    cout<<"-1"<<endl;
}
signed main(){
    ios::sync_with_stdio(false);
    cin.tie(0);cout.tie(0);
    cin>>M;
    memset(map,-1,sizeof(map));
    memset(ans,0,sizeof(ans));
    for(int i=1;i<=M;i++){
        cin>>mx>>my>>mt;
        for(int j=0;j<5;j++){ //标记陨石的位置 
            int nx=mx+dir[j][0];
            int ny=my+dir[j][1];
            if(check(nx,ny)&&(map[nx][ny]==-1 || map[nx][ny]>mt))
                map[nx][ny]=mt;
        }
    }
    vis[0][0]=1;
    BFS();
    
    return 0;
}
复制代码

赠送:P3395 路障 - 洛谷 | 计算机科学教育新生态 (luogu.com.cn)

复制代码
#include<iostream> 
#include<queue>
#include<cstring>
using namespace std;
const int N=1010;
int T,n,bx[2*N],by[2*N];
int dir[4][2]={{1,0},{-1,0},{0,1},{0,-1}};
bool flag,vis[N][N],map[N][N];
struct node{
    int x,y,t;
};
#define check(a,b) (a>=1&&a<=n&&b>=1&&b<=n)
void BFS(){
    node begin,next;
    begin.x=1;
    begin.y=1;
    begin.t=0;
    queue<node> q;
    q.push(begin);
    while(!q.empty()){
        begin=q.front();
        q.pop();
        if(begin.x==n&&begin.y==n){
            flag=true;
            cout<<"Yes"<<endl;
            return ;
        }
        for(int i=0;i<4;i++){
            int nx=begin.x+dir[i][0];
            int ny=begin.y+dir[i][1];
            if(check(nx,ny) && !vis[nx][ny] && !map[nx][ny]){
                vis[nx][ny]=1;
                next.x=nx;
                next.y=ny;
                next.t=begin.t+1;
                q.push(next);
            }
        }
        map[bx[begin.t]][by[begin.t]]=1;
    }
    cout<<"No"<<endl;
}
signed main(){
    ios::sync_with_stdio(false);
    cin.tie(0);cout.tie(0);
    cin>>T;
    while(T--){
        memset(vis,0,sizeof(vis));
        memset(map,0,sizeof(map));
        memset(bx,0,sizeof(bx));
        memset(by,0,sizeof(by));
        cin>>n;
        for(int i=1;i<=2*n-2;i++) cin>>bx[i]>>by[i];
        vis[1][1]=1;
        flag=false;
        BFS();
    }
    return 0;
}
复制代码

P1036 [NOIP2002 普及组] 选数 - 洛谷 | 计算机科学教育新生态 (luogu.com.cn)

复制代码
#include<iostream>
#include<algorithm>
#include<cstring>
#include<cmath>
using namespace std;
int n,k,a[30],ans=0;
bool isprime(int x){
    if(x==1) return false;
    for(int i=2;i<=sqrt(x);i++){
        if(x%i==0) return false;
    }
    return true;
}
void DFS(int pos,int sum,int cnt){
    if(cnt==k){
        if(isprime(sum)) ans++;
        return ;
    }
    for(int i=pos;i<=n;i++) DFS(i+1,sum+a[i],cnt+1);
}
signed main(){
    ios::sync_with_stdio(false);
    cin.tie(0);cout.tie(0);
    cin>>n>>k;
    for(int i=1;i<=n;i++) cin>>a[i];
    DFS(1,0,0);
    cout<<ans<<endl;
    return 0;
}
复制代码

P2036 [COCI2008-2009 #2] PERKET - 洛谷 | 计算机科学教育新生态 (luogu.com.cn)

复制代码
#include<iostream>
#include<algorithm>
#include<cstring>
using namespace std;
const int INF=0x3f3f3f3f;
int n,s[15],b[15],vis[15],ans,ss,bb;
void DFS(int cnt){
    if(cnt>n){
        return ;
    }
    for(int i=1;i<=n;i++){
        if(!vis[i]){
            ss*=s[i];
            bb+=b[i];
            ans=min(ans,abs(ss-bb));
            vis[i]=1;
            DFS(cnt+1);
            vis[i]=0;
            ss/=s[i];
            bb-=b[i];
        }
    }
}
signed main(){
    ios::sync_with_stdio(false);
    cin.tie(0);cout.tie(0);
    cin>>n;
    for(int i=1;i<=n;i++) cin>>s[i]>>b[i];
    ans=INF;
    ss=1;
    bb=0;
    DFS(1);
    cout<<ans<<endl;
    return 0;
}
复制代码

P1605 迷宫 - 洛谷 | 计算机科学教育新生态 (luogu.com.cn)

复制代码
#include<iostream>
#include<cstring>
using namespace std;
int map[10][10],vis[10][10];
int N,M,T,SX,SY,FX,FY,TX,TY,ans;
int dir[4][2]={{1,0},{-1,0},{0,-1},{0,1}};
#define check(x,y) (x>=1&&x<=N&&y>=1&&y<=M)
void DFS(int x,int y){
    if(x==FX&&y==FY){
        ans++;
        return ;
    }else{
        for(int i=0;i<4;i++){
            int nx=x+dir[i][0];
            int ny=y+dir[i][1];
            if(check(nx,ny)&&!vis[nx][ny]&&!map[nx][ny]){
                vis[x][y]=1;
                DFS(nx,ny);
                vis[x][y]=0;
            }
        }
    }    
}
signed main(){
    ios::sync_with_stdio(false);
    cin.tie(0);cout.tie(0);
    cin>>N>>M>>T;
    for(int i=1;i<=N;i++)
        for(int j=1;j<=M;j++)
            map[i][j]=0;
    cin>>SX>>SY>>FX>>FY;
    for(int i=1;i<=T;i++){
        cin>>TX>>TY;
        map[TX][TY]=1;
    } 
    ans=0;
    DFS(SX,SY);
    cout<<ans<<endl;
    
    return 0;
}
复制代码

 P1101 单词方阵 - 洛谷 | 计算机科学教育新生态 (luogu.com.cn)

复制代码
#include<iostream>
#include<algorithm>
#include<cstring>
using namespace std;
const int N=110;
int n;
int dir[8][2]={{-1,-1},{-1,0},{-1,1},{0,-1},{0,1},{1,-1},{1,0},{1,1}};
char map[N][N],aim[]="yizhong";
bool vis[N][N];
struct node{
    int x,y;
}path[N];
void DFS(int x,int y,node path[],int k,int cur){
    if(cur==7){
        for(int i=0;i<7;i++) vis[path[i].x][path[i].y]=1;
    }else{
        int nx=x+dir[k][0];
        int ny=y+dir[k][1];
        if(cur==6||map[nx][ny]==aim[cur+1]){
            path[cur].x=x;
            path[cur].y=y;
            DFS(nx,ny,path,k,cur+1);
        }
    }
}
signed main(){
    ios::sync_with_stdio(false);
    cin.tie(0);cout.tie(0);
    cin>>n;
    for(int i=0;i<n;i++){
        for(int j=0;j<n;j++) cin>>map[i][j];
    }
    memset(vis,0,sizeof(vis));
    for(int i=0;i<n;i++){
        for(int j=0;j<n;j++){
            if(map[i][j]=='y'){
                for(int k=0;k<8;k++){
                    int x=i+dir[k][0];
                    int y=j+dir[k][1];
                    if(map[x][y]=='i') DFS(i,j,path,k,0);
                }
            }
        }
    }
    for(int i=0;i<n;i++){
        for(int j=0;j<n;j++){
            if(vis[i][j]) cout<<map[i][j];
            else cout<<"*";
        }
        cout<<endl;
    }
    return 0;
}
复制代码

 P2404 自然数的拆分问题 - 洛谷 | 计算机科学教育新生态 (luogu.com.cn)

复制代码
#include<iostream>
#include<algorithm>
#include<cstring>
using namespace std;
int n;
int a[15]={1};
void print(int tt){
    for(int i=1;i<tt;i++) cout<<a[i]<<"+";
    cout<<a[tt]<<endl;
}
void DFS(int s,int t){
    for(int i=a[t-1];i<=s;i++){
        if(i<n){
            a[t]=i;
            s-=i;
            if(!s) print(t);
            else DFS(s,t+1);
            s+=i;
        }
    }
}
signed main(){
    ios::sync_with_stdio(false);
    cin.tie(0);cout.tie(0);
    cin>>n;
    DFS(n,1);
    
    return 0;
}
复制代码

 P1596 [USACO10OCT] Lake Counting S - 洛谷 | 计算机科学教育新生态 (luogu.com.cn)

复制代码
#include<iostream>
#include<algorithm>
#include<cstring>
using namespace std;
int n,m,ans;
int dir[8][2]={{0,1},{0,-1},{1,0},{-1,0},{-1,1},{-1,-1},{1,-1},{1,1}};
char map[110][110];
#define check(a,b) (a>=1&&a<=n&&b>=1&&b<=m)
void DFS(int x,int y){
    for(int i=0;i<8;i++){
        int nx=x+dir[i][0];
        int ny=y+dir[i][1];
        if(check(nx,ny)&&map[nx][ny]=='W'){
            map[nx][ny]='.';
            DFS(nx,ny);
        }
    }
}
signed main(){
    ios::sync_with_stdio(false);
    cin.tie(0);cout.tie(0);
    cin>>n>>m;
    for(int i=1;i<=n;i++){
        for(int j=1;j<=m;j++) cin>>map[i][j];
    }
    ans=0;
    for(int i=1;i<=n;i++){
        for(int j=1;j<=m;j++){
            if(map[i][j]=='W'){
                ans++;
                DFS(i,j);
            }
        }
    }
    cout<<ans<<endl;
    return 0;
}
复制代码

 P1162 填涂颜色 - 洛谷 | 计算机科学教育新生态 (luogu.com.cn)

复制代码
#include<iostream> 
#include<cstring>
using namespace std;
int n,a[40][40],b[40][40];
int dir[4][2]={{1,0},{-1,0},{0,1},{0,-1}};
void DFS(int x,int y){
    if(x<0 || x>n+1 || y<0 || y>n+1 || a[x][y]!=0) return ;
    a[x][y]=1;
    for(int i=0;i<4;i++){
        int nx=x+dir[i][0];
        int ny=y+dir[i][1];
        DFS(nx,ny);
    }
}
signed main(){
    ios::sync_with_stdio(false);
    cin.tie(0);cout.tie(0);
    cin>>n;
    for(int i=1;i<=n;i++){
        for(int j=1;j<=n;j++){
            cin>>b[i][j];
            if(!b[i][j]) a[i][j]=0;
            else a[i][j]=2;
        }
    }
    DFS(0,0);
    for(int i=1;i<=n;i++){
        for(int j=1;j<=n;j++){
            if(!a[i][j]) cout<<2<<" ";
            else cout<<b[i][j]<<" ";
        }
        cout<<endl;
    }        
    return 0;
}
复制代码

 赠送:P1506 拯救oibh总部 - 洛谷 | 计算机科学教育新生态 (luogu.com.cn)

复制代码
#include<iostream>
#include<algorithm>
#include<cstring>
using namespace std;
int x,y,ans;
int dir[4][2]={{1,0},{-1,0},{0,-1},{0,1}};
int a[510][510];
void DFS(int dx,int dy){
    if(dx<0 || dx>x+1 || dy<0 || dy>y+1 || a[dx][dy]) return ;
    a[dx][dy]=2;
    for(int i=0;i<4;i++){
        DFS(dx+dir[i][0],dy+dir[i][1]);
    }
}
signed main(){
    ios::sync_with_stdio(false);
    cin.tie(0);cout.tie(0);
    cin>>x>>y;
    char ch;
    for(int i=1;i<=x;i++){
        for(int j=1;j<=y;j++){
            cin>>ch;
            if(ch=='*') a[i][j]=1;
            else a[i][j]=0;
        }
    }
    DFS(0,0);
    for(int i=1;i<=x;i++){
        for(int j=1;j<=y;j++){
            if(!a[i][j]) ans++;
        }
    }
    cout<<ans<<endl;

    return 0;
}
复制代码

 P1825 [USACO11OPEN] Corn Maze S - 洛谷 | 计算机科学教育新生态 (luogu.com.cn)

复制代码
#include<iostream> 
#include<queue>
#include<cstring>
using namespace std;
int N,M,bx,by;
int dir[4][2]={{1,0},{-1,0},{0,1},{0,-1}};
char map[400][400];
bool vis[400][400];
struct node{
    int x,y,t;
};
#define check(a,b) (a>=1&&a<=N&&b>=1&&b<=M)
void changedir(int &cx,int &cy){
    for(int i=1;i<=N;i++){
        for(int j=1;j<=M;j++){
            if(map[i][j]==map[cx][cy]&&(i!=cx || j!=cy)){
                cx=i;
                cy=j;
                return ;
            }
        }
    }
}
void BFS(){
    node begin,next;
    begin.x=bx;
    begin.y=by;
    begin.t=0;
    queue<node> q;
    q.push(begin);
    while(!q.empty()){
        begin=q.front();
        q.pop();
        if(map[begin.x][begin.y]=='='){
            cout<<begin.t<<endl;
            return ;
        }
        if(map[begin.x][begin.y]>='A'&&map[begin.x][begin.y]<='Z')
             changedir(begin.x,begin.y);
        for(int i=0;i<4;i++){
            int nx=begin.x+dir[i][0];
            int ny=begin.y+dir[i][1];
            if(check(nx,ny)&&!vis[nx][ny]&&map[nx][ny]!='#'){
                next.x=nx;
                next.y=ny;
                next.t=begin.t+1;
                vis[nx][ny]=1;
                q.push(next);
            }
        }    
    }
}
signed main(){
    ios::sync_with_stdio(false);
    cin.tie(0);cout.tie(0);
    cin>>N>>M;
    for(int i=1;i<=N;i++){
        for(int j=1;j<=M;j++){
            cin>>map[i][j];
            if(map[i][j]=='@'){
                bx=i;
                by=j;
            }
        }
    }
    vis[bx][by]=1;
    BFS();
    
    return 0;
}
复制代码

 排列:P1706 全排列问题 - 洛谷 | 计算机科学教育新生态 (luogu.com.cn)

STL函数写法:

复制代码
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const int N=15;
int n,a[N];
signed main(){
    ios::sync_with_stdio(false);
    cin.tie(0);cout.tie(0);
    cin>>n;
    for(int i=1;i<=n;i++) a[i]=i;
    sort(a+1,a+1+n);
    do{
        for(int i=1;i<=n;i++) cout<<"    "<<a[i];        
        cout<<endl;
    }while(next_permutation(a+1,a+1+n));
    
    return 0;
}
复制代码

DFS回溯写法:

复制代码
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const int INF=0x3f3f3f3f;
int n,vis[100],a[100];
void DFS(int k){
    if(k==n){
        for(int i=1;i<=n;i++) cout<<setw(5)<<a[i];
        cout<<endl;
        return ;
    }
    for(int i=1;i<=n;i++){
        if(!vis[i]){
            vis[i]=1;
            a[k+1]=i;
            DFS(k+1);
            vis[i]=0;
        }
    }
}
signed main(){
    ios::sync_with_stdio(false);
    cin.tie(0);cout.tie(0);
    cin>>n;
    DFS(0);
    
    return 0;
}
复制代码

组合:P1157 组合的输出 - 洛谷 | 计算机科学教育新生态 (luogu.com.cn)

复制代码
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const int INF=0x3f3f3f3f;
int n,r,a[100];
void DFS(int t){
    if(t>r){
        for(int i=1;i<=r;i++) cout<<setw(3)<<a[i];
        cout<<endl;
        return ;
    }
    for(int i=a[t-1]+1;i<=n;i++){
        a[t]=i;
        DFS(t+1);
    }
}
signed main(){
    ios::sync_with_stdio(false);
    cin.tie(0);cout.tie(0);
    cin>>n>>r;
    DFS(1);
    
    return 0;
}
复制代码

 

 

  

posted @   ACCbulb  阅读(10)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· 无需6万激活码!GitHub神秘组织3小时极速复刻Manus,手把手教你使用OpenManus搭建本
· C#/.NET/.NET Core优秀项目和框架2025年2月简报
· Manus爆火,是硬核还是营销?
· 终于写完轮子一部分:tcp代理 了,记录一下
· 【杭电多校比赛记录】2025“钉耙编程”中国大学生算法设计春季联赛(1)
点击右上角即可分享
微信分享提示