回顧二分與bfs(或者說是遞推)和簡單模擬

清風紫雪發表於2019-07-23

今天,陽光正好,適合敲程式碼,諸事皆宜。

先來兩道簡單的模擬題。

第一道

機器翻譯

輸出為5.

程式碼思路:很明顯需要用到佇列來存單詞,在建立一個bool陣列來儲存佇列中有沒有這個單詞,需不需要向外界查詢,如果需要並且佇列可以容下,則加入佇列並將bool陣列標記在佇列中有該單詞,如果佇列容不下,則將隊頭彈出,並用bool陣列標記彈出的數字在該佇列中沒有。

程式碼:

#include<bits/stdc++.h>
using namespace std;
queue<int> ss;
bool mp[1010];
int n,m;
int main()
{
    int i,j,t,ans=0;
    cin>>m>>n;
    for(i=0;i<n;i++)
    {
        cin>>t;
        if(ss.size()>m)
        {
            int f=ss.front();
            mp[f]=0;
            ss.pop();
        }
        if(mp[t]==0)
        {
            ss.push(t);
            ans++;
            mp[t]=1;
        }
    }
    cout<<ans<<endl;
    return 0;
}

第二道

神奇的幻方

輸出為:

8 1 6
3 5 7
4 9 2
思路:按題中步驟執行即可
首先找到1的位置,他在x=1,y=n/2+1;
然後判斷若x在第一行,但不在最後一列,就讓下一個數在x=n,y++的位置;
若不在第一行,在最後一列,就讓下一個數在x--,y=1的位置;
若在第一行最後一列,就讓下一個數在x++,y的位置;
若既不在最後一行也不在最後一列,並且右上方沒有數字,則下一個數在x--,y++的位置;
以上四個都不滿足就在x++,y的位置;
程式碼:
#include<bits/stdc++.h>
using namespace std;
int a[111][111];
int main()
{
    int n,i,j,x,y;
    cin>>n;
    x=1;y=n/2+1;
    for(i=1;i<=n*n;i++)
    {
        a[x][y]=i;
        if(x==1&&y!=n)
        {
            x=n;y++;
        }
        else if(y==n&&x!=1)
        {
            y=1;x--;
        }
        else if(x==1&&y==n)
        {
            x++;
        }
        else if(a[x-1][y+1]==0)
        {
            x--;y++;
        }
        else
            x++;
    }
    for(i=1;i<=n;i++)
    {
        for(j=1;j<=n;j++)
            cout<<a[i][j]<<" ";
        cout<<endl;
    }
    return 0;
}

一道二分的題

靈能探索

連結:https://ac.nowcoder.com/acm/contest/639/A
來源:牛客網
思路:二分邊界是從[靈能的最小值,靈能總和],check()函式的書寫:迴圈陣列,累加如果大於等於mid的值,則讓con++,s=0,繼續迴圈直到結束。判斷con的值是否大於等於題中輸入的組數,大於返回1,證明mid的值還可以在大,就讓l=mid+1,ans=mid,如果con的值不大於,證明mid的值大了,則需要r=mid-1,在進行判斷找出合適的mid的值。

程式碼:

#include<bits/stdc++.h>
using namespace std;
const long long N=100005;
long long n,k,ans,a[N];
long long check(long long x)
{
    long long i,j,s=0,con=0;
    for(i=0;i<n;i++)
    {
        s+=a[i];
        if(s>=x)
        {
            con++;
            s=0;
        }
    }
    if(con>=k)
        return 1;
    return 0;
}
int main()
{
    long long i,j,minx=100005,sum=0;
    long long l,r,mid;
    cin>>n>>k;
    for(i=0;i<n;i++)
    {
        cin>>a[i];
        minx=min(minx,a[i]);
        sum+=a[i];
    }
    l=minx;r=sum;
    while(l<=r)
    {
        mid=(l+r)/2;
        if(check(mid))
        {
            l=mid+1;
            ans=mid;
        }
        else
            r=mid-1;
    }
    cout<<ans<<endl;
}

一個乍一看是一道bfs搜尋題,然而他卻是到遞推題。

好心酸。。。。。

過河卒

連結:https://ac.nowcoder.com/acm/contest/639/B
來源:牛客網

先說說bfs的思路:從(1,1)開始搜尋,遇到馬或者超界就不放入佇列裡,最後如果佇列到達了終點則ans++;

程式碼:可惜只過了75%的資料

#include<bits/stdc++.h>
using namespace std;
const int mod=10000007;
int n,m,x,y,ans;
int xx[2]={1,0},yy[2]={0,1};
int v[1000][1000];
int vis[1000][1000];
struct node
{
    int a,b;
};
void bfs(int X,int Y)
{
    vis[X][Y]=1;
    node t;
    t.a=X;t.b=Y;
    queue<node> p;
    p.push(t);
    while(!p.empty())
    {
        node g=p.front();
        p.pop();
        if(g.a==n&&g.b==m)
        {
            ans++;
            continue;
        }
        for(int i=0;i<2;i++)
        {
            int w=g.a+xx[i];
            int l=g.b+yy[i];
            if(v[w][l]!=1&&vis[w][l]!=1&&w>=1&&w<=n&&l>=1&&l<=m)
            {
                p.push(node{w,l});
            }
        }
    }
    return ;
}
int main()
{
    int i,j;
    cin>>n>>m>>x>>y;
    v[x][y]=1;
    v[x-1][y-2]=1;
    v[x-2][y-1]=1;
    v[x-2][y+1]=1;
    v[x-1][y+2]=1;
 
    v[x+1][y-2]=1;
    v[x+2][y-1]=1;
    v[x+1][y+2]=1;
    v[x+2][y+1]=1;
    bfs(1,1);
    cout<<ans%mod<<endl;
    return 0;
}

正解:遞推dp[i][j]=dp[i-1][j]+dp[i][j-1]

現將馬的所有可去的位置用v[][]的二維陣列標記上,然後將表格的第一行和第一列dp[][]賦值為1,如果途中遇到馬的位置,則停下結束迴圈,馬下面的將不會走故而可以結束迴圈,最終用二重迴圈從(2,2)開始計算如果不是馬的位置則dp[i][j]=(dp[i-1][j]+dp[i][j-1])%mod,否則dp[i][j]=0;

最終輸出dp[n][m]%mod的值,在這裡特別宣告一定要在計算dp[i][j]的時候也要取mod,因為數字很大容易超限,導致錯誤。

程式碼:

#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const ll mod=10000007;
ll n,m,ans,x,y;
int x1[9]={0,-2,-1,1,2,2,1,-1,-2};
int yy[9]={0,1,2,2,1,-1,-2,-2,-1};
ll dp[1004][1004];
ll v[1004][1004];
int main()
{
    ll i,j;
    cin>>n>>m>>x>>y;
    v[x][y]=1;
    for(i=1;i<=8;i++)
    {
        if(x+x1[i]>=1&&y+yy[i]>=1)
            v[x+x1[i]][y+yy[i]]=1;
    }
    for(i=1;i<=n;i++)
    {
        if(v[i][1]==0)
            dp[i][1]=1;
        else
            break;
    }
    for(j=1;j<=m;j++)
    {
        if(v[1][j]==0)
            dp[1][j]=1;
        else
            break;
    }
    for(i=2;i<=n;i++)
    {
        for(j=2;j<=m;j++)
        {
            if(v[i][j]==0)
                dp[i][j]=(dp[i-1][j]+dp[i][j-1])%mod;
            else
                dp[i][j]=0;
        }
    }
    cout<<dp[n][m]%mod<<endl;
    return 0;
}

ACM之旅仍在繼續,加油!!少年

 

 

相關文章