zoukankan      html  css  js  c++  java
  • 紫书 动态规划例题

    https://vjudge.net/contest/176767#overview

    A - A Spy in the Metro

    #include <bits/stdc++.h>  
    using namespace std;  
    const int N = 55, M = 205;  
    int t[N], d[N][M];  //j时刻在i号车站剩下的最小总等待时间  
    bool l[N][M], r[N][M];  //j时刻在i号车站是否有往左(右)的车  
      
    int main()  
    {  
        int n, m, ti, cur, cas = 0;  
      
        while(~scanf("%d", &n), n)  
        {  
            scanf("%d", &ti);  
            memset(l, 0, sizeof(l)), memset(r, 0, sizeof(r));  
            for(int i = 1; i < n; ++i) scanf("%d", &t[i]);  
      
            scanf("%d", &m);  //cur时刻车站j是否有往右的车  
            for(int i = 1; i <= m; ++i)  
            {  
                scanf("%d", &cur);  
                for(int j = 1; j <= n; ++j)  
                    r[j][cur] = 1, cur += t[j];  
            }  
            scanf("%d", &m);  //cur时刻车站j是否有往左的车  
            for(int i = 1; i <= m; ++i)  
            {  
                scanf("%d", &cur);  
                for(int j = n; j >= 1; --j)  
                    l[j][cur] = 1, cur += t[j - 1];  
            }  
      
            memset(d, 0x3f, sizeof(d));  
            d[n][ti] = 0;  
            for(int j = ti - 1; j >= 0; --j)  
            {  
                for(int i = 1; i <= n; ++i)  
                {  
                    d[i][j] = d[i][j + 1] + 1;   //在i车站等1单位时间  
                    if(l[i][j]) d[i][j] = min(d[i][j], d[i - 1][j + t[i - 1]]);  //往左  
                    if(r[i][j]) d[i][j] = min(d[i][j], d[i + 1][j + t[i]]);  //往右  
                }  
            }  
      
            printf("Case Number %d: ", ++cas);  
            if(d[1][0] > ti) puts("impossible");  
            else printf("%d
    ", d[1][0]);  
        }  
        return 0;  
    }  

    最长递增子序列变形

    C

    #include<iostream>
    #include<cstdio>
    #include<cmath>
    #include<cstring>
    #include<sstream>
    #include<algorithm>
    #include<queue>
    #include<deque>
    #include<iomanip>
    #include<vector>
    #include<cmath>
    #include<map>
    #include<stack>
    #include<set>
    #include<memory>
    #include<list>
    #include<string>
    using namespace std;
    typedef long long LL;
    typedef unsigned long long ULL;
    #define MAXN  1009
    #define L 31
    #define INF 1000000009
    #define eps 0.00000001
    
    int n;
    double dp[MAXN][MAXN];
    double dist[MAXN][MAXN];
    struct node
    {
        double x, y;
    }a[MAXN];
    double D(const node & a, const node &b)
    {
        return sqrt((a.x - b.x)*(a.x - b.x) + (a.y - b.y)*(a.y - b.y));
    }
    int main()
    {
        while (scanf("%d", &n) != EOF)
        {
            for (int i = 1; i <= n; i++)
            {
                scanf("%lf%lf", &a[i].x, &a[i].y);
                for (int j = 1; j < i; j++)
                    dist[i][j] = D(a[i], a[j]);
            }
            for (int i = n - 1; i >= 2; i--)
            {
                for (int j = 1; j < i; j++)
                {
                    if (i == n - 1) dp[i][j] = dist[n][i] + dist[n][j];
                    else dp[i][j] = min(dp[i + 1][j] + dist[i + 1][i], dp[i + 1][i] + dist[i + 1][j]);
                }
            }
            printf("%.2lf
    ", dist[2][1] + dp[2][1]);
        }
    }

    D

    #include<iostream>
    #include<cstdio>
    #include<cmath>
    #include<cstring>
    #include<sstream>
    #include<algorithm>
    #include<queue>
    #include<deque>
    #include<iomanip>
    #include<vector>
    #include<cmath>
    #include<map>
    #include<stack>
    #include<set>
    #include<memory>
    #include<list>
    #include<string>
    using namespace std;
    typedef long long LL;
    typedef unsigned long long ULL;
    #define MAXN  1009
    #define L 31
    #define INF 1000000009
    #define eps 0.00000001
    
    /*
    单向TSP 书上给的是反向DP 这样更好输出解
    */
    int n, m;
    int a[11][MAXN], dp[11][MAXN], path[11][MAXN];
    int main()
    {
        while (scanf("%d%d", &m, &n) != EOF)//m行n 列
        {
            for (int i = 0; i < m; i++)
            {
                for (int j = 0; j < n; j++)
                {
                    scanf("%d", &a[i][j]);
                }
            }
            int ans = INF, first = 0;
            for (int j = n - 1; j >= 0; j--)
            {
                for (int i = 0; i < m; i++)
                {
                    if (j == n - 1) dp[i][j] = a[i][j];
                    else
                    {
                        int row[3] = { i + 1,i - 1,i };
                        if (i == 0)    row[1] = m - 1;
                        if (i == m - 1)    row[0] = 0;
                        sort(row, row + 3);
                        dp[i][j] = INF;
                        for (int k = 0; k < 3; k++)
                        {
                            int v = dp[row[k]][j + 1] + a[i][j];
                            if (v < dp[i][j])
                            {
                                dp[i][j] = v, path[i][j] = row[k];
                            }
                        }
                    }
                    if (j == 0 && dp[i][0] < ans)
                    {
                        ans = dp[i][0], first = i;
                    }
                }
            }
            printf("%d", first + 1);
            for (int i = path[first][0], j = 1; j < n; i = path[i][j], j++)
            {
                printf(" %d", i + 1);
            }
            printf("
    %d
    ", ans);
        }
    }

    E

    #include<iostream>
    #include<cstdio>
    #include<cmath>
    #include<cstring>
    #include<sstream>
    #include<algorithm>
    #include<queue>
    #include<deque>
    #include<iomanip>
    #include<vector>
    #include<cmath>
    #include<map>
    #include<stack>
    #include<set>
    #include<memory>
    #include<list>
    #include<string>
    using namespace std;
    typedef long long LL;
    typedef unsigned long long ULL;
    #define MAXN  1009
    #define L 31
    #define INF 1000000009
    #define eps 0.00000001
    /*
    对于某一种灯泡 要么全部替换 要么全都不替换
    证明:如果替换N个剩下M个能带来 P*N的收益,那么替换剩下的M个可以带来P*M+K的收益。K是节约掉的搭建电源的收益
    dp[i]表示满足前i种灯泡需求的花费    区域考虑!考虑某一片都用这个灯泡
    */
    struct node
    {
        int v, k, c, l;
        bool operator<(const node& rhs)
        {
            return v < rhs.v;
        }
    }a[MAXN];
    int dp[MAXN], pre[MAXN], n;
    int main()
    {
        while (scanf("%d", &n), n)
        {
            memset(pre, 0, sizeof(pre));
            memset(dp, INF, sizeof(dp));
            for (int i = 1; i <= n; i++)
                scanf("%d%d%d%d", &a[i].v, &a[i].k, &a[i].c, &a[i].l);
            sort(a + 1, a + n + 1);
            int sum = 0;
            dp[0] = 0;
            for (int i = 1; i <= n; i++)
            {
                pre[i] = pre[i - 1] + a[i].l;
            }
            
            for (int i = 1; i <= n; i++)
            {
                for (int j = 0; j < i; j++)
                {
                    dp[i] = min(dp[j] + (pre[i] - pre[j])*a[i].c + a[i].k,dp[i]);
                }
            }
            printf("%d
    ", dp[n]);
        }
    }

    G

    #include<iostream>
    #include<cstdio>
    #include<cmath>
    #include<cstring>
    #include<sstream>
    #include<algorithm>
    #include<queue>
    #include<deque>
    #include<iomanip>
    #include<vector>
    #include<cmath>
    #include<map>
    #include<stack>
    #include<set>
    #include<memory>
    #include<list>
    #include<string>
    using namespace std;
    typedef long long LL;
    typedef unsigned long long ULL;
    #define MAXN  1009
    #define L 31
    #define INF 1000000009
    #define eps 0.00000001
    /*
    先用n2 时间维护一个二维数组记录i-j是不是回文字串
    然后dp
    */
    char str[MAXN];
    int dp[MAXN];
    bool vis[MAXN][MAXN];
    int main()
    {
        int n;
        scanf("%d", &n);
        while (n--)
        {
            memset(vis, false, sizeof(vis));
            scanf("%s", str + 1);
            int l = strlen(str + 1);
            for (int i = 1; i <= l; i++)
                vis[i][i] = true;
            for (int i = 1; i < l; i++)
            {
                if (str[i] == str[i + 1])
                    vis[i][i + 1] = true;
                else
                    vis[i][i + 1] = false;
            }
            for (int k = 2; k <= l; k++)
            {
                for (int i = 1; i <= l; i++)
                {
                    int j = i + k;
                    if (j > l) break;
                    if (str[i] == str[j] && vis[i + 1][j - 1])
                        vis[i][j] = true;
                }
            }
            memset(dp, INF, sizeof(dp));
            dp[0] = 0;
            for (int i = 1; i <= l; i++)
            {
                for (int j = 0; j < i; j++)
                {
                    if (vis[j+1][i])
                        dp[i] = min(dp[i], dp[j] + 1);
                }
            }
            printf("%d
    ", dp[l]);
        }
    }

    H

    #include <iostream>
    #include <cstdio>
    #include <cstring>
    #include <string>
    #include <cmath>
    #define INF 10e7
    using namespace std;
    int T,len1,len2;
    int dp[5005][5005];
    int st1[27],st2[27],ed1[27],ed2[27];
    char s1[5005],s2[5005];
    
    void dp_solve()
    {
        //int cnt=0,res=INF;
        for(int i=0; i<=len1; i++)
            for(int j=0; j<=len2; j++)
            {
                int cnt=0,res=INF;
                for(int k=0; k<26; k++)
                    if((i>=st1[k]||j>=st2[k])&&(i<ed1[k]||j<ed2[k]))//此处判断有多少种颜色已经出现但尚未结束
                        cnt++;
                if(i>0) res=min(res,dp[i-1][j]);
                if(j>0) res=min(res,dp[i][j-1]);
                dp[i][j]=cnt+(res==INF ? 0:res);
            }
        cout<<dp[len1][len2]<<endl;
    }
    
    int main()
    {
        cin>>T;
        while(T--)
        {
            scanf("%s%s",s1+1,s2+1);
            len1=strlen(s1+1);
            len2=strlen(s2+1);
            for(int i=0; i<26; i++)
            {
                st1[i]=st2[i]=INF;
                ed1[i]=ed2[i]=0;
            }
            int tmp;
            for(int i=1; i<=len1; i++)
            {
                tmp=s1[i]-'A';
                if(st1[tmp]==INF)  st1[tmp]=i;
                ed1[tmp]=i;
            }
            for(int i=1; i<=len2; i++)
            {
                tmp=s2[i]-'A';
                if(st2[tmp]==INF)  st2[tmp]=i;
                ed2[tmp]=i;
            }
            dp_solve();
        }
        return 0;
    }

    I

    #include <iostream>
    #include <cstdio>
    #include <cstring>
    #include <string>
    #include <cmath>
    #define INF 10e7
    using namespace std;
    int T,len1,len2;
    int dp[5005][5005];
    int st1[27],st2[27],ed1[27],ed2[27];
    char s1[5005],s2[5005];
    
    void dp_solve()
    {
        //int cnt=0,res=INF;
        for(int i=0; i<=len1; i++)
            for(int j=0; j<=len2; j++)
            {
                int cnt=0,res=INF;
                for(int k=0; k<26; k++)
                    if((i>=st1[k]||j>=st2[k])&&(i<ed1[k]||j<ed2[k]))//此处判断有多少种颜色已经出现但尚未结束
                        cnt++;
                if(i>0) res=min(res,dp[i-1][j]);
                if(j>0) res=min(res,dp[i][j-1]);
                dp[i][j]=cnt+(res==INF ? 0:res);
            }
        cout<<dp[len1][len2]<<endl;
    }
    
    int main()
    {
        cin>>T;
        while(T--)
        {
            scanf("%s%s",s1+1,s2+1);
            len1=strlen(s1+1);
            len2=strlen(s2+1);
            for(int i=0; i<26; i++)
            {
                st1[i]=st2[i]=INF;
                ed1[i]=ed2[i]=0;
            }
            int tmp;
            for(int i=1; i<=len1; i++)
            {
                tmp=s1[i]-'A';
                if(st1[tmp]==INF)  st1[tmp]=i;
                ed1[tmp]=i;
            }
            for(int i=1; i<=len2; i++)
            {
                tmp=s2[i]-'A';
                if(st2[tmp]==INF)  st2[tmp]=i;
                ed2[tmp]=i;
            }
            dp_solve();
        }
        return 0;
    }

    I 树形DP

    #include<iostream>
    #include<cstdio>
    #include<cmath>
    #include<cstring>
    #include<sstream>
    #include<algorithm>
    #include<queue>
    #include<deque>
    #include<iomanip>
    #include<vector>
    #include<cmath>
    #include<map>
    #include<stack>
    #include<set>
    #include<memory>
    #include<list>
    #include<string>
    using namespace std;
    typedef long long LL;
    typedef unsigned long long ULL;
    #define MAXN  55
    #define L 31
    #define INF 1000000009
    #define eps 0.00000001
    
    /*
    dp[i][j] 为切割小木棍i-j点的费用
    dp[i][j] = a[j]-a[i](切割第一刀的费用) + dp[i][k] + dp[k][j] 从中间的k点切
    O(n3)
    */
    int l, n, a[MAXN];
    int dp[MAXN][MAXN];
    int main()
    {
        while (scanf("%d", &l), l)
        {
            memset(dp, INF, sizeof(dp));
            memset(a, 0, sizeof(a));
            scanf("%d", &n);
            for (int i = 1; i <= n; i++)
                scanf("%d", &a[i]);
            for (int i = 0; i <= n + 1; i++)
                dp[i][i] = 0;
            for (int i = 0; i < n + 1; i++)
                dp[i][i + 1] = a[i + 1] - a[i];
            a[0] = 0, a[n + 1] = l;
            for (int k = 1; k <= n + 1; k++)
            {
                for (int i = 0; i + k <= n + 1; i++)
                {
                    int j = i + k;
                    for (int t = i + 1; t < j; t++)
                        dp[i][j] = min(dp[i][j], dp[i][t] + dp[t][j] + a[j] - a[i]);
                }
            }
            printf("The minimum cutting is %d.
    ", dp[0][n + 1]);
        }
    }
  • 相关阅读:
    219. Contains Duplicate II
    189. Rotate Array
    169. Majority Element
    122. Best Time to Buy and Sell Stock II
    121. Best Time to Buy and Sell Stock
    119. Pascal's Triangle II
    118. Pascal's Triangle
    88. Merge Sorted Array
    53. Maximum Subarray
    CodeForces 359D Pair of Numbers (暴力)
  • 原文地址:https://www.cnblogs.com/joeylee97/p/7353815.html
Copyright © 2011-2022 走看看