week 14

这篇文章包含了10个不同的动态规划或算法问题的解决方案,包括路径计数、最大和上升子序列、数字加一、跳跳游戏、异或和或的判断、01序列、出栈序列判断、序列维护以及网格判断问题。每个问题都提供了思路和C++代码实现。
摘要由CSDN通过智能技术生成

1.

路径计数

思路:dp倒推

代码:

#include<bits/stdc++.h>
using namespace std;
int mapp[1001][1001];
int dp[1001][1001];
int n;
const int P = 1e9+7;
int main(){
    cin>>n;
    for(int i=1;i<=n;i++){
        for(int j=1;j<=n;j++){
            cin>>mapp[i][j]; 
        } 
    }
    for(int i=n;i>=1;i--){
        for(int j=n;j>=1;j--){
            if(i==n){
                dp[i][j]=1;
            }
            else dp[i][j]=(dp[i+1][j]+dp[i][j+1])%P;
            if(mapp[i][j]==0)dp[i][j]=0;
        }
    }
    cout<<dp[1][1];
    return 0;
}

2.

最大和上升子序列


思路:dp记录当前的最大值,循环找前面比它小的

#include<bits/stdc++.h>
using namespace std;
int a[100010];
int dp[100010];
int n;
int to[100100];
int main(){
    cin>>n;
    for(int i=1;i<=n;i++){
        cin>>a[i];
    }
    int maxx=-1e9;
    for(int i=1;i<=n;i++){
        dp[i]=a[i];
        for(int j=1;j<i;j++){
            if(a[j]<a[i]){
                dp[i]=max(a[i]+dp[j],dp[i]);
            }
        }
        maxx=max(maxx,dp[i]);
    }
    cout<<maxx;
    return 0;
} 

3.

加一


思路:预处理每个数加到一万的情况,再跳着加

#include<bits/stdc++.h>
#define LL long long
using namespace std;
LL shu[10],n,m;
const LL P=1e9+7;
LL yu_chu[10][10];
LL yu[10][10];
int main(){
    //预处理 
    for(LL i=0;i<=9;i++){
        yu_chu[i][i]=1;
        LL k=10000;
        while(k-10>=0){
            k-=10;
            LL js=yu_chu[i][9];
            for(LL j=9;j>=1;j--){
                yu_chu[i][j]=(yu_chu[i][j]+yu_chu[i][j-1])%P;
            }
            yu_chu[i][0]=(yu_chu[i][0]+js)%P;
            yu_chu[i][1]=(yu_chu[i][1]+js)%P;
        }
    }
    for(LL i=0;i<=9;i++){
        yu[i][i]=1;
        LL k=1000;
        while(k-10>=0){
            k-=10;
            LL js=yu[i][9];
            for(LL j=9;j>=1;j--){
                yu[i][j]=(yu[i][j]+yu[i][j-1])%P;
            }
            yu[i][0]=(yu[i][0]+js)%P;
            yu[i][1]=(yu[i][1]+js)%P;
        }
    }
    //cout<<"begin"<<endl;
    cin>>n;
    while(n--){
        memset(shu,0,sizeof(shu));
        string str;
        cin>>str>>m;
        LL len = str.length();
        for(LL w=0;w<len;w++){
            shu[str[w]-'0']++;
        }
        while(m-10000>=0){
            m=m-(LL)10000;
            //cout<<m<<endl;
            LL jia[10];
            memset(jia,0,sizeof(jia));
            for(LL j=0;j<=9;j++){
                for(LL i=0;i<=9;i++){
                    jia[j]=(jia[j]+yu_chu[i][j]*shu[i])%P;
                }
            }
            for(int i=0;i<=9;i++){
                shu[i]=jia[i];
            }
        }
        while(m-1000>=0){
            m=m-(LL)1000;
            //cout<<m<<endl;
            LL jia[10];
            memset(jia,0,sizeof(jia));
            for(LL j=0;j<=9;j++){
                for(LL i=0;i<=9;i++){
                    jia[j]=(jia[j]+yu[i][j]*shu[i])%P;
                }
            }
            for(int i=0;i<=9;i++){
                shu[i]=jia[i];
            }
        }
        while(m>=10){
            m-=10;
            LL js=shu[9];
            for(LL i=9;i>=1;i--){
                shu[i]=(shu[i]+shu[i-1])%P;
            }
            shu[0]=(shu[0]+js)%P;
            shu[1]=(shu[1]+js)%P;
        }
        //cout<<m<<endl;
        while(m--){
            LL sum=shu[9];
            for(LL i=9;i>=1;i--){
                shu[i]=shu[i-1];
            }
            shu[0]=(sum)%P;
            shu[1]=(shu[1]+sum)%P;
        }
        //cout<<"EVA"<<endl;
        LL ans=0;
        for(LL i=0;i<=9;i++){
            ans=(shu[i]+ans)%P;
            //cout<<shu[i]<<" ";
        }
        cout<<ans<<endl;
    }
    return 0;
}

4.

跳跳


思路:简单的记录斜率就行

代码;

#include<bits/stdc++.h>
using namespace std;
int a[1000],b[1000];
map<int,map<int,int>>EVA;
int n;
int main(){
    int ans=0;
    cin>>n;
    for(int i=1;i<=n;i++){
        cin>>a[i]>>b[i];
    }
    for(int i=1;i<=n;i++){
        for(int j=1;j<=n;j++){
            if(i==j)continue;
            if(a[i]==a[j]){
                if(EVA[1][0]==0){
                    EVA[1][0]=1;
                    //cout<<"1 0\n";
                    ans++;
                }
                if(EVA[-1][0]==0){
                    EVA[-1][0]=1;
                    //cout<<"-1 0\n";
                    ans++;
                }
                continue;
            }
            if(b[i]==b[j]){
                if(EVA[0][1]==0){
                    EVA[0][1]=1;
                    //cout<<"0 1\n";
                    ans++;
                }
                if(EVA[0][-1]==0){
                    EVA[0][-1]=1;
                    //cout<<"0 -1\n";
                    ans++;
                }
                continue;
            }
            int x=(a[i]-a[j]);
            int y=(b[i]-b[j]);
            int jsx=1;
            int jsy=1;
            if(x<0){
                jsx=-1;
                x=-x;
            }
            if(y<0){
                jsy=-1;
                y=-y;
            }
            jsx*=x/__gcd(x,y);
            jsy*=y/__gcd(x,y);
            //cout<<"EVA"<<endl;
            //cout<<jsx<<" "<<jsy<<endl;
            if(EVA[jsx][jsy]==0){
                EVA[jsx][jsy]=1;
                ans++;
            }
        }
    }
    cout<<ans;
    return 0;
}

5.

异或和或


思路:

(0,1)===>(1,1)

(0,0)===>(0,0)

(1,1)===>(0,1)

0不能无中生有,1不能全部消失

代码:

#include<bits/stdc++.h>
using namespace std;
int n;
int main(){
    cin>>n;
    while(n--){
        string s1,s2;
        cin>>s1>>s2;
        if(s1.length()!=s2.length())cout<<"NO"<<endl;
        else{
            int a,b,len;
            a=b=0;
            len=s1.length();
            for(int i=0;i<len;i++){
                if(s1[i]=='0')a++;
                if(s2[i]=='0')b++; 
            }
            if(a+b==len && a*b==0){
                cout<<"NO"<<endl;
                continue;
            }
            if((a!=len && b==len) || (a==len && b!=len)){
                cout<<"NO"<<endl;
            }
            else cout<<"YES"<<endl;
            
        }
    }
    return 0;
}

6.

01序列


思路:

算每个点的左边有几个,右边有几个

0要单独判断

代码:

#include<bits/stdc++.h>
using namespace std;
long long k;
long long cnt=0;
queue<long long>EVA;
struct cjc{
    long long left;
    long long right;
}a[1000010];
int main(){
    cin>>k;
    string str;
    cin>>str;
    long long js=0;
    if(k==0){
        long long ANS=0;
        for(long long i=0;i<str.length();i++){
            if(str[i]=='0'){
                js++;
            }
            else{
                ANS+=(js*(js+1))/2;
                js=0;
            }
        }
        if(js)ANS+=(js*(js+1))/2;
        cout<<ANS;
        return 0;
    }
    js=0;
    for(long long i=0;i<str.length();i++){
        if(str[i]=='1'){
            a[++cnt].left=js;
            if(cnt>1){
                a[cnt-1].right=js;
            }
            js=0;
        }
        else{
            js++;
        }
    }
    if(js)a[cnt].right=js;
    long long ans=0;
    for(long long i=k;i<=cnt;i++){
        ans+=(a[i-k+1].left+1)*(a[i].right+1);
    }
    cout<<ans;
    return 0;
}

7.

出栈序列判断


按照要求出就是了,判断当前的数小就不断pop

代码:

#include<bits/stdc++.h>
using namespace std;
int n;
int wei=1;
stack<int>EVA;
int a[1000010];
int main(){
    cin>>n;
    for(int i=1;i<=n;i++)cin>>a[i];
    for(int i=1;i<=n;i++){
        EVA.push(i);
        printf("push %d\n",i);
        while(!EVA.empty()){
            if(EVA.top()<a[wei])break;
            while(!EVA.empty()){
                if(EVA.top()==a[wei])break;
                printf("pop\n");
                EVA.pop();
            }
            EVA.pop();
            printf("pop\n");
            wei++;
        }
    }
    while(!EVA.empty()){
        printf("pop\n");
        EVA.pop();
    }
    return 0;
}

8.

序列维护


简单的链表维护

代码;

#include<bits/stdc++.h>
using namespace std;
int n;
struct cjc{
    int val;
    int left;
    int right;
}shu[10001];
int cnt=1;
int main(){
    cin>>n;
    shu[0].right = 1;
    shu[1].left = 0;
    for(int i=1;i<=n;i++){
        string op;
        int x,y;
        cin>>op;
        if(op=="insert"){
            cin>>x>>y;
            int wei=0;
            shu[++cnt].val=y;
            int js=0;
            while(js<x){
                js++;
                wei=shu[wei].right;
            }
            int hou = shu[wei].right;
            shu[cnt].left = wei;
            shu[cnt].right = hou;
            shu[wei].right = cnt;
            shu[hou].left = cnt;
        }
        else if(op=="query"){
            cin>>x;
            int wei=0;
            int js=0;
            while(js<x){
                wei=shu[wei].right; 
                js++;
            }
            cout<<shu[wei].val<<endl;
        }
        else{
            cin>>x;
            int wei=0;
            int js=0;
            while(js<x){
                wei=shu[wei].right; 
                js++;
            }
            int pre = shu[wei].left;
            int hou = shu[wei].right;
            shu[pre].right = hou;
            shu[hou].left  = pre;
        }
    }
    return 0;
}

9.

网格判断


模拟

代码:

#include<bits/stdc++.h>
using namespace std;
int hen[100],shu[100];
char mapp[1001][1001];
int n;
int main(){
    cin>>n;
    for(int i=1;i<=n;i++){
        for(int j=1;j<=n;j++){
            cin>>mapp[i][j];
            hen[i]+=(int)(mapp[i][j]=='B');
            shu[j]+=(int)(mapp[i][j]=='B');
        }
    }
    int ans=0; 
    for(int i=1;i<=n;i++){
        if(hen[i]!=n/2 || shu[i]!=n/2){
            ans=1;
            break;
        }
    }
    for(int i=1;i<=n;i++){
        for(int j=2;j<=n-1;j++){
            if(mapp[i][j]==mapp[i][j-1] && mapp[i][j]==mapp[i][j+1]){
                ans=1;
                break; 
            }
        }
    }
    for(int i=1;i<=n;i++){
        for(int j=2;j<=n-1;j++){
            if(mapp[j][i]==mapp[j-1][i] && mapp[j][i]==mapp[j+1][i]){
                ans=1;
                break; 
            }
        }
    }
    cout<<(ans?"0":"1");
    return 0;
}

10.

整齐的数组


思路:

orz ---->__gcd()

代码;

#include<bits/stdc++.h>
using namespace std;
int n,x,a[100010];
int main(){
    cin>>n;
    while(n--){
        cin>>x;
        int ans=0;
        for(int i=1;i<=x;i++){
            cin>>a[i];
            if(i>=2){
                if(a[i]!=a[i-1]){
                    if(ans==0){
                        ans=abs(a[i]-a[i-1]);
                    }
                    else{
                        ans=__gcd(ans,abs(a[i]-a[i-1]));
                    }
                }
            }
        }
        cout<<(ans==0?-1:ans)<<endl;
    }
    return 0;
} 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值