• 动态规划


    [CF] k-Tree

    寒假手速赛第一场

    题意:...

    时间复杂度:(O(n*k))

    思路:直接模拟,选或者不选,dp数组第一维为和,第二维为是否包含重量大于d的边

    (考虑组合数做法?)

    https://codeforces.com/group/GlRm4CeuZ9/contest/266331/problem/C

    #include<bits/stdc++.h>
    using namespace std;
    const long long mod = 1e9 + 7;
    const int maxn = 1e5 + 5;
    long long dp[maxn][3];
    int main() {
        int n, k, d;
        scanf("%d%d%d", &n, &k, &d);
        dp[0][0] = 1;
        for (int i = 1; i <= n;i++) {
            for (int j = 1; j <= k;j++) {   
                if(i>=j) {
                    if(j<d) {
                        dp[i][0] = (dp[i][0] + dp[i - j][0]) % mod;
                        dp[i][1] = (dp[i][1] + dp[i - j][1]) % mod;
                    }
                    else if(j>=d) {
                        dp[i][1] = (dp[i][1] + dp[i - j][0] + dp[i - j][1]) % mod;
                    }
                }
            }
        }
        cout << dp[n][1] << endl;
    }
    

    操作集锦

    https://ac.nowcoder.com/acm/contest/4853/C

    题意

    找到长度为k的本质不同的子序列的个数

    思路

    按照长度枚举

    for (int i = 1; i <= n; i++) {
        int v = s[i] - 'a';
        pre[i] = pos[v];
        pos[v] = i;
    }
    for (int i = 1; i <= k; i++) {
        for (int j = 1; j <= n; j++) {
            if (!pre[j])
                dp[i][j] = (dp[i][j - 1] + dp[i - 1][j - 1] + (i > 1 ? 0 : 1)) % mod;
    
            else
                dp[i][j] = (dp[i][j-1]+dp[i-1][j-1]-dp[i-1][pre[j]-1]+mod) % mod;
        }
    }
    

    代码 : https://xlorpaste.cn/gewr71

    [CF] LCIS

    寒假手速赛第一场

    题意:求给定两个序列的公共最长子序列

    时间复杂度:(O(n^2))

    思路:增加一个指针,一个记录路径的数组即可

    https://codeforces.com/group/GlRm4CeuZ9/contest/266331/problem/D

    #include<bits/stdc++.h>
    using namespace std;
    
    const int maxn = 500 + 5;
    
    int a[maxn],s[maxn];
    int dp[maxn], pre[maxn];
    
    int main() {
        int n;
        scanf("%d", &n);
        for (int i = 1; i <= n;i++){
            scanf("%d", &a[i]);
        }
        int m;
        scanf("%d", &m);
        for (int i = 1; i <= m;i++) {
            scanf("%d", &s[i]);
        }
        //
        for (int i = 1; i <= n;i++) {
            int x = 0;
            for (int j = 1; j <= m; j++) {
                if(a[i]<s[j])
                    continue;
                if(a[i]>s[j]) {
                    if(dp[j]>dp[x]){
                        x = j;
                    }
                }
                if(a[i] == s[j]) {
                    if(dp[j]<dp[x]+1) {
                        dp[j] = dp[x] + 1;
                        pre[j] = x;
                    }
                }
            }
        }
        //
        int ans = 0;
        int t = 0;
    
        for (int i = 1; i <= m;i++) {
            if(dp[i]>dp[t]){
                ans = dp[i];
                t = i;
            }
        }
        printf("%d
    ", ans);
    
        vector<int> v;
        while(t) {
            v.push_back(s[t]);
            t = pre[t];
        }
    
        int sz = v.size();
        for (int i = sz - 1; i >= 0;i--) {
            printf("%d", v[i]);
            if(i == 0) printf("
    ");
            else printf(" ");
        }
    }
    

    [CF] Elevator

    https://codeforces.com/group/GlRm4CeuZ9/contest/266331/problem/E

    题意:某电梯可以承载4个人,上、下电梯均需要1s,上、下一层均需要1s,乘客按照排队顺序上电梯

    给定每个乘客所在楼层和目标楼层,问送完所有乘客的最短时间

    #include<bits/stdc++.h>
    using namespace std;
    const int maxn = 2000 + 5;
    const int inf = 0x3f3f3f3f;
    int dp[maxn][10][10][10][10];
    int x[maxn], y[maxn];
    int n;
    int dis(int x,int y) {
        return abs(x - y);
    }
    int dfs(int i,int cur,int a,int b,int c) {
        if(dp[i][cur][a][b][c])
            return dp[i][cur][a][b][c];
        int ans = inf;
        if(i>n) {
            if(!a&&!b&&!c)
                return 0;
            if(a)
                ans = min(ans, dfs(i, a, 0, b, c) + dis(cur, a) + 1);
            if(b)
                ans = min(ans, dfs(i, b, a, 0, c) + dis(cur, b) + 1);
            if(c)
                ans = min(ans, dfs(i, c, a, b, 0) + dis(cur, c) + 1);
            return dp[i][cur][a][b][c] = ans;
        }
            if(a)
                ans = min(ans, dfs(i, a, 0, b, c) + dis(cur, a) + 1);
            if(b)
                ans = min(ans, dfs(i, b, a, 0, c) + dis(cur, b) + 1);
            if(c)
                ans = min(ans, dfs(i, c, a, b, 0) + dis(cur, c) + 1);
            if(a&&b&&c) {
                ans = min(ans, dfs(i + 1, y[i], a, b, c) + dis(cur, x[i]) + dis(x[i], y[i]) + 2);
                ans = min(ans, dfs(i + 1, a, y[i], b, c) + dis(cur, x[i]) + dis(x[i], a) + 2);
                ans = min(ans, dfs(i + 1, b, a, y[i], c) + dis(cur, x[i]) + dis(x[i], b) + 2);
                ans = min(ans, dfs(i + 1, c, a, b, y[i]) + dis(cur, x[i]) + dis(x[i], c) + 2);
            }
            else {
                if(!a)
                    ans = min(ans, dfs(i + 1, x[i], y[i], b, c) + dis(cur, x[i]) + 1);
                else if(!b)
                    ans = min(ans, dfs(i + 1, x[i], a, y[i], c) + dis(cur, x[i]) + 1);
                else if(!c)
                    ans = min(ans, dfs(i + 1, x[i], a, b, y[i]) + dis(cur, x[i]) + 1);   
            }
            return dp[i][cur][a][b][c] = ans;
    }
    int main() {
        scanf("%d", &n);
        for (int i = 1;i<=n;i++)
            scanf("%d%d", &x[i], &y[i]);
        printf("%d
    ", dfs(1, 1, 0, 0, 0));
    }
    

    [CF] 状压 Marbles

    https://codeforces.com/contest/1215/problem/E

    #include<bits/stdc++.h>
    using namespace std;
    
    const int inf = 0x3f3f3f3f;
    const int maxn = 4e5 + 100;
    int a[maxn];
    int tot;
    
    long long pre[30][30], cnt[30];
    long long dp[1 << 21];
    
    map<int, int> mp;
    int main()
    {
        int n;
        scanf("%d", &n);
        for (int i = 1; i <= n;i++) {
            scanf("%d", &a[i]);
            if(!mp[a[i]]){
                mp[a[i]] = tot++;
            }
        }
        for (int i = 1; i <= n;i++) {
            int x = mp[a[i]];
            for (int j = 0; j < tot;j++) {
                pre[x][j] += cnt[j];
            }
            cnt[x]++;
        }
        memset(dp, 0x3f, sizeof(dp));
        dp[0] = 0;
        for (int i = 1; i < (1 << tot); i++) {
            for (int j = 0; j < tot;j++) {
                if(i&(1<<j)) {
                    long long temp = 0;
                    for (int k = 0; k < tot;k++) {
                        if(j!=k&&!(i&(1<<k))) {
                            temp += pre[j][k];
                        }
                    }
                    dp[i] = min(dp[i], dp[i ^ (1 << j)] + temp);
                }
            }
        }
        printf("%lld
    ", dp[(1 << tot) - 1]);
    }
    

    [CF1216F] Wi-Fi

    https://codeforces.com/contest/1216/problem/F

    #include<bits/stdc++.h>
    using namespace std;
    const int maxn = 2e5 + 100;
    int a[maxn];
    long long dp[maxn], tr[maxn << 2];
    
    
    void update(int rt,int l,int r,int pos,long long v) {
        if(l==pos&&r==pos) {
            tr[rt] = v;
            return;
        }
        int mid = (l + r) >> 1;
        if(pos<=mid) {
            update(rt << 1, l, mid, pos, v);
        }
        else {
            update(rt << 1 | 1, mid + 1, r, pos, v);
        }
        tr[rt] = min(tr[rt << 1], tr[rt << 1 | 1]);
    }
    
    long long query(int rt,int l,int r,int L,int R){
        if(L<=l&&r<=R) {
            return tr[rt];
        }
        int mid = (l + r) >> 1;
        long long ans = 1e18;
        if(L<=mid)
            ans = min(ans, query(rt << 1, l, mid, L, R));
        if(R>mid)
            ans = min(ans, query(rt << 1 | 1, mid + 1, r, L, R));
        return ans;
    }
    
    int main() {
        int n, k;
        scanf("%d%d", &n, &k);
        for (int i = 1; i <= n;i++) {
            scanf("%1d", &a[i]);
        }
        memset(tr, 0x3f, sizeof(tr));
        memset(dp, 0x3f, sizeof(dp));
        dp[0] = 0;
        update(1, 0, n, 0, 0);
        for (int i = 1; i <= n;i++) {
            if(a[i]==0)
                dp[i] = min(dp[i], dp[i - 1] + i);
            else {
                int x = min(i + k, n);
                int y = max(i - k - 1, 0);
                dp[x] = min(dp[x], query(1, 0, n, y, n) + i);
                update(1, 0, n, x, dp[x]);
            }
            dp[i] = min(dp[i], query(1, 0, n, i + 1, n));
            update(1, 0, n, i, dp[i]);
        }
        printf("%lld
    ", dp[n]);
    }
    
    #include<bits/stdc++.h>
    using namespace std;
     
    const int maxn = 2e5 + 100;
     
    long long dp[maxn];
    int f[maxn],a[maxn];
     
    int main() {
        int n, k;
        scanf("%d%d", &n, &k);
        for (int i = 1; i <= n;i++) {
            scanf("%1d", &a[i]);
        }
        f[n + 1] = 2 * n + k;
        for(int i = n;i>=1;i--) {
            if(a[i]==1) {
                f[i] = i;
            }
            else {
                f[i] = f[i + 1];
            }
        }
     
        for(int i=1;i<=n;i++) {
            dp[i] = dp[i - 1] + i;
            int t = f[max(1, i - k)];
            if(t<=i+k) {
                dp[i] = min(dp[i], dp[max(1, t - k) - 1] + t);
            }
        }
        printf("%lld
    ", dp[n]);
    }
    

    最短路

    #include<bits/stdc++.h>
    using namespace std;
    const int maxn = 2e5 + 100;
    int n, k;
    int a[maxn];
    long long dis[maxn];
    int vis[maxn];
    struct edge{
        int to;
        long long v;
    };
    vector<edge> G[maxn];
    struct node{
        int to;
        long long dis;
        bool operator<(const node& b)const
        {
            return dis>b.dis;
        }
    };
    void dijkstra(int s) {
        for (int i = 0; i <= n + 1;i++)
            dis[i] = 1e18;
    
        priority_queue<node> q;
        q.push((node){s, 0});
        dis[s] = 0;
    
        while(!q.empty()) {
            node t = q.top();
            q.pop();
            int u = t.to;
            if(vis[u])
                continue;
            vis[u] = 1;
            int sz = G[u].size();
            for (int i = 0; i < sz; i++) {
                int v = G[u][i].to;
                long long d = G[u][i].v;
                if(dis[u]+d<dis[v]) {
                    dis[v] = dis[u] + d;
                    q.push((node){v, dis[v]});
                }
            }
        }
    }
    int main() {
        scanf("%d%d", &n, &k);
        for (int i = 1; i <= n;i++) {
            scanf("%1d", &a[i]);
        }
        for (int i = 1; i <= n;i++) {
            long long v = i;
            G[i].push_back((edge){i + 1, v});
            G[i].push_back((edge){i - 1, 0});
            if(a[i]==1) {
                int l = max(i - k, 1);
                int r = min(i + k, n) + 1;
                G[l].push_back((edge){r, v});
            }
        }
        G[n+1].push_back((edge){n, 0});
        dijkstra(1);
        printf("%lld
    ", dis[n + 1]);
    }
    
    #include<bits/stdc++.h>
    using namespace std;
    const int maxn = 4e5 + 100;
     
    long long dp[maxn];
    int a[maxn];
     
     
    int main() {
        int n, k;
        scanf("%d%d", &n, &k);
        for (int i = 1; i <= n;i++) {
            scanf("%1d", &a[i]);
        }
     
        deque<int> d;
        d.push_back(0);
     
        for (int i = 1; i <= n + k;i++) {
            dp[i] = dp[i - 1] + i;
            if(i-k>0&&a[i-k]==1) {
                while(!d.empty()&&d.front()<i-2*k-1)
                    d.pop_front();
                dp[i] = min(dp[i], dp[d.front()] + i - k);
            }
            while(!d.empty()&&dp[d.back()]>=dp[i])
                d.pop_back();
            d.push_back(i);
        }
        long long ans = 1e18;
        for (int i = n; i <= n + k;i++) {
            ans = min(ans, dp[i]);
        }
        printf("%lld
    ", ans);
    }
    
    

    [CF1324E] Sleeping Schedule

    https://codeforces.com/contest/1324/problem/E

    要么选(a_i),要么选(a_i-1)

    #include<bits/stdc++.h>
    using namespace std;
    const int maxn = 2000 + 5;
    int a[maxn];
    int dp[maxn][maxn];
    int main() {
        int n,h,l,r;
        cin >> n >> h >> l >> r;
        for (int i = 1; i <= n;i++) {
            scanf("%d", &a[i]);
        }
        memset(dp,-0x3f,sizeof(dp));
        dp[0][0] = 0;
        for (int i = 1; i <= n;i++) {
            for (int j = 0; j < h;j++) {
                int x = (j + a[i] - 1) % h;
                int f = 0;
                if(l<=x&&x<=r)
                    f = 1;
                dp[i][x] = max(dp[i-1][j] + f, dp[i][x]);
                x = (j + a[i]) % h;
                if(l<=x&&x<=r)
                    f = 1;
                else
                    f = 0;
                dp[i][x] = max(dp[i-1][j] + f, dp[i][x]);
            }
        }
        int ans = 0;
        for (int i = 0; i < h;i++) {
            ans = max(ans, dp[n][i]);
        }
        cout << ans << endl;
    }
    
    

    状压DP

    找朋友

    赵队出的题,找朋友

    #include <bits/stdc++.h>
    #include<stdint.h>
    using namespace std;
    #define int long long
    #define scan(n) scanf("%lld", &(n))
    #define scann(n, m) scanf("%lld%lld", &(n), &(m))
    #define scannn(a, b, c) scanf("%lld%lld%lld", &(a), &(b), &(c))
    #define prin(n) printf("%lld", (n))
    #define pb push_back
    #define mp make_pair
    #define ms(a) memset(a, 0, sizeof(a))
    #define fo(i, a, b) for (int i = (a); i <= (b); i++)
    #define ro(i, a, b) for (int i = (a); i >= (b); i--)
    #define dbg(args...) do {cout << #args << " : "<< args << endl;} 
    const int inf = 0x3f3f3f3f;
    const int maxn = (1<<21);
    int x[25],y[25];
    int n,f;
    double dp[maxn];
    bool check(int s,int t){
        for(int i=1;i<=n;i++){
            int x=(1<<i);
            if((!(s&x))&&(t&x))return false;
        }
        return true;
    }
    double dis(int i,int j){
        return sqrt((x[i]-x[j])*(x[i]-x[j])+(y[i]-y[j])*(y[i]-y[j]));
    }
    double min_dis(int t,int j){
        vector<double>v;
        for(int i=1;i<=n;i++){
            int x=(1<<i);
            if(t&x){
                v.pb(dis(i,j));
            }
        }
        sort(v.begin(),v.end());
        if(v.size()<=1)return inf;
        return v[0]+v[1];
    }
    int32_t main() {
        int T;scan(T);
        while(T--){
            scan(n);
            int s=0;
            int xx=((1<<(n+1))-1)^1;
            for(int i=0;i<=maxn-1;i++)dp[i]=inf;
            fo(i,1,n){
                scannn(x[i],y[i],f);
                if(f)s^=(1<<i);
            }
            dp[s]=0;
            for(int i=s;i<=xx;i++){
                if(!check(i,s))continue;
                fo(j,1,n){
                    int t=(1<<j);
                    if((i&t)&&(!(s&t))){
                        int x=i^t;
                        dp[i]=min(dp[x]+min_dis(x,j),dp[i]);
                    }
                    else continue;
                }
            }
            if(dp[xx]==inf){
                cout<<"No Solution
    ";
                continue;
            }
            printf("%.6lf
    ",dp[xx]);
        }
        return 0;
    }
    

    区间DP

    [CF1199F] Rectangle Painting

    https://codeforces.com/contest/1199/problem/F

    给定一个(n imes n)的矩阵,由("#”,".")组成,每次可以将(h imes w)矩形内的("#")变成(".")

    花费为(max(h,w)),求将所有("#")变成(".")的最小花费

    #include<bits/stdc++.h>
    #define fo(i,a,b) for(int i=a;i<=b;i++)
    using namespace std;
    char a[55][55];
    int f[55][55][55][55];
    int dp(int x,int y,int xx,int yy){
        if(f[x][y][xx][yy]!=-1)return f[x][y][xx][yy];
        int ans=max(xx-x+1,yy-y+1);
        fo(i,x,xx-1)ans=min(ans,dp(x,y,i,yy)+dp(i+1,y,xx,yy));
        fo(i,y,yy-1)ans=min(ans,dp(x,y,xx,i)+dp(x,i+1,xx,yy));
        return f[x][y][xx][yy]=ans;
    }
    int main(){
        int n;scanf("%lld",&n);
        fo(i,1,n)scanf("%s",a[i]+1);
        memset(f,-1,sizeof(f));
        fo(x,1,n){
            fo(y,1,n){
                fo(xx,1,n){
                    fo(yy,1,n){
                        if(x>xx||y>yy)f[x][y][xx][yy]=0;
                        if(x==xx&&y==yy)f[x][y][xx][yy]=(a[x][y]=='#'?1:0);
                    }
                }
            }
        }
        cout<<dp(1,1,n,n)<<endl;
        
    }
    
  • 相关阅读:
    刷题[CISCN2019 华东南赛区]Web4
    刷题[GWCTF 2019]你的名字
    刷题[b01lers2020]Life on Mars
    刷题[SUCTF 2018]GetShell
    洛谷入门2-分支结构
    洛谷入门3-循环结构:回文质数、斐波那契数列
    洛谷入门3-循环结构:金币、最长连号
    洛谷入门3-循环结构:津津的储蓄计划
    C++类成员初始化方法
    英语听力
  • 原文地址:https://www.cnblogs.com/guaguastandup/p/12585162.html
Copyright © 2020-2023  润新知