现在的位置: 首页 > 综合 > 正文

Assignment 4: Dynamic Programming (DP)

2013年09月08日 ⁄ 综合 ⁄ 共 5784字 ⁄ 字号 评论关闭
  • 2663 Tri Tiling (1)

  • 1163 The Triangle (1)

  • 1160 Post Office (2)

  • 2033 Alphacode (2)

  • 1159 Palindrome (3)

  • 1050 To the Max (4)

  • 2127 Greatest Common Increasing Subsequence (6)

  • 1655 Balancing Act (6)

  • 2292 Optimal Keypad (6)

  • 2430 Lazy Cows (7)

  • 2066 Minimax Triangulation (8, challenge problem)

  • 1038 Bugs Integrated, Inc. (9, challenge problem)

    poj2292

    DP的每个状态都对应一个string类的路径

    #include<cstdio>
    #include<cstring>
    #include<string>
    #include<iostream>
    using namespace std;
    #define inf 1000000000
    int d[35][35], path[35][35], p[35], cnt[35];
    string start[35][35];
    
    char print(int i) {
        if (i <= 26)
            return i + 'a' - 1;
        if (i == 27)
            return '+';
        if (i == 28)
            return '*';
        if (i == 29)
            return '/';
        if (i == 30)
            return '?';
    }
    
    int gao(char ch) {
        if (ch >= 'a' && ch <= 'z')
            return ch - 'a' + 1;
        if (ch == '+')
            return 27;
        if (ch == '*')
            return 28;
        if (ch == '/')
            return 29;
        if (ch == '?')
            return 30;
    }
    char s[35];
    
    int cal(int x, int y) {
        int temp = 0, i, deep = 1;
        for (i = x; i <= y; ++i) {
            temp += cnt[i] * deep;
            deep++;
        }
        return temp;
    }
    
    int min(int x, int y) {
        return x < y ? x : y;
    }
    
    int main() {
        int T, n, i, j, k, temp, ans;
        scanf("%d", &T);
        while (T--) {
            memset(path, 0, sizeof (path));
            memset(cnt, 0, sizeof (cnt));
            scanf("%d", &n);
            while (n--) {
                scanf("%s", s);
                for (i = 0; s[i]; ++i) {
                    cnt[gao(s[i])]++;
                }
            }
            for (i = 0; i <= 30; ++i) {
                for (j = 0; j <= 30; ++j) {
                    start[i][j].clear();
                    //    cout<<"star"<<start[i][j]<<endl;
                    d[i][j] = inf;
                }
            }
            for (i = 2; i <= 30; ++i) {
                j = 1;
                d[j][i] = cal(1, i - 1);
                start[1][i] = start[1][i] + print(i);
                for (++j; j <= min(i - 1, 11); ++j) {
                    d[j][i] = d[j - 1][i - 1] + cnt[i - 1];
                    path[i][j] = i - 1;
                    start[j][i] = start[j - 1][i - 1] + print(i);
                    for (k = i - 2; k >= j; --k) {
                        temp = d[j - 1][k] + cal(k, i - 1);
                        if (temp < d[j][i] || (temp == d[j][i] && start[j - 1][k] + print(i) < start[j][i])) {
                            d[j][i] = temp;
                            path[i][j] = k;
                            start[j][i] = start[j - 1][k] + print(i);
                        }
                    }
                }
            }
            ans = inf;
            int pp;
            for (i = 11; i <= 30; ++i) {
                temp = d[11][i] + cal(i, 30);
                //   printf("i=%d d11i=%d temp=%d\n", i, d[11][i], temp);
                if (temp < ans || (temp == ans && start[11][i] < start[11][pp])) {
                    ans = temp;
                    pp = i;
                    //   cout<<"###"<<start[11][pp]<<endl;
                }
            }
            cout << start[11][pp] << endl;
        }
        return 0;
    }

    poj2430

    状态DP,每次4种状态互相转移

    #include<cstdio>
    #include<cstring>
    #include<algorithm>
    using namespace std;
    
    struct NODE {
        int x, h;
    
        bool operator<(const NODE& t)const {
            return x < t.x;
        }
    };
    NODE node[1010];
    int tot, place[1010], map[1010];
    int d[1010][1010][5];
    int wide[5] = {0, 1, 1, 2, 2};
    
    int can(int a, int b) {
        if (a == 1 && (b & 2))
            return 0;
        if (a == 2 && (b & 1))
            return 0;
        return 1;
    }
    
    int main() {
        int n, b, k, i, j, cnt, s1, s2, temp;
        scanf("%d%d%d", &n, &k, &b);
        for (i = 0; i < n; ++i) {
            scanf("%d%d", &node[i].h, &node[i].x);
        }
        sort(node, node + n);
        //  for (i = 0; i < n; ++i)
        //    printf("* %d %d\n", node[i].h, node[i].x);
        place[0] = node[0].x;
        map[0] += node[0].h;
        tot = 1;
        for (i = 1; i < n; ++i) {
            if (node[i].x == node[i - 1].x) {
                map[tot - 1] += node[i].h;
            } else {
                place[tot] = node[i].x;
                map[tot] += node[i].h;
                ++tot;
            }
        }
        memset(d, -1, sizeof (d));
        for (s1 = 1; s1 < 4; ++s1) {
            if (!can(s1, map[0]))
                continue;
            d[0][1][s1] = wide[s1];
        }
        d[0][2][4] = 2;
        for (i = 0; i < tot - 1; ++i) {
            for (j = 1; j <= k; ++j) {
                for (s1 = 1; s1 <= 4; ++s1) {
                    if (d[i][j][s1] < 0)
                        continue;
                    for (s2 = 1; s2 <= 4; ++s2) {
                        if (!can(s2, map[i + 1]))
                            continue;
                        if ((s1 == s2 || (s1 == 4 && s2 != 3))) {
                            temp = d[i][j][s1] + (place[i + 1] - place[i]) * wide[s2];
                            if (d[i + 1][j][s2] == -1 || temp < d[i + 1][j][s2])
                                d[i + 1][j][s2] = temp;
                            //       printf("i+1=%d j=%d s2=%d temp=%d d=%d\n", i + 1, j, s2, temp, d[i + 1][j][s2]);
                        }
                        if (s2 == 4 && j + 2 <= k) {
                            temp = d[i][j][s1] + 2;
                            if (d[i + 1][j + 2][s2] == -1 || temp < d[i + 1][j + 2][s2])
                                d[i + 1][j + 2][s2] = temp;
                        }
                        if (s2 <= 3 && j + 1 <= k) {
                            temp = d[i][j][s1] + wide[s2];
                            if (d[i + 1][j + 1][s2] == -1 || temp < d[i + 1][j + 1][s2])
                                d[i + 1][j + 1][s2] = temp;
                        }
                        if (s2 == 4 && s1 != 3 && j + 1 <= k) {
                            temp = d[i][j][s1] + place[i + 1] - place[i] + 1;
                            if (d[i + 1][j + 1][s2] == -1 || temp < d[i + 1][j + 1][s2])
                                d[i + 1][j + 1][s2] = temp;
                        }
                    }
                }
            }
        }
        int ans = 0x7fffffff;
        for (j = 1; j <= 4; ++j)
            if (d[tot - 1][k][j] > 0 && d[tot - 1][k][j] < ans)
                ans = d[tot - 1][k][j];
        printf("%d\n", ans);
        return 0;
    }

    poj2066

    判弦是否在形内后,直接DP

    #include<stdio.h>
    #include<stdlib.h>
    int x[55], y[55], cost[55][55];
    int cas, n, i, j, k, best, sum;
    #define maxn 1<<30
    #define min(a,b) ((a)<(b)?(a):(b))
    #define max(a,b) ((a)>(b)?(a):(b))
    #define fuhao(a) ((a)>(0)?(1):(0))
    #define w(i,j,k) ((x[j]-x[i])*(y[k]-y[i])-(y[j]-y[i])*(x[k]-x[i]))
    
    int main() {
        scanf("%d", &cas);
        while (cas--) {
            scanf("%d", &n);
            for (i = 0; i < n; i++) {
                scanf("%d%d", &x[i], &y[i]);
                if (i > 1)sum += w(0, i - 1, i);
                else sum = 0;
                cost[i][(i + 1) % n] = 0;
            }
            for (i = 2; i < n; i++) {
                for (j = 0; j < n; j++) {
                    cost[j][(j + i) % n] = maxn;
                    for (k = 1; k < i; k++) {
                        best = w(j, (j + k) % n, (j + i) % n);
                        if (fuhao(sum) == fuhao(best)) {
                    //        printf("sum=%d best=%d\n", sum, best);
                            cost[j][(j + i) % n] = min(cost[j][(j + i) % n], max(max(abs(best), cost[(j + k) % n][(j + i) % n]), cost[j][(j + k) % n]));
                        }
                    }
                }
            }
            printf("%.1lf\n", (double) cost[1][0] / 2);
        }
    }

    poj1038

    状态DP,三进制状态

    #include<cstdio>
    #include<cstring>
    inline int max(int a,int b){
        return a>b?a:b;
    }
    bool mat[13][155];
    int d[2][60000],state[2][60000],b[13],p[13],cnt[2];
    int m,n,pre,cur,ans,j;
    
    void print(int x){
        printf("print 3th of %d\n",x);
        int i;
        for(i=0;i<m;++i) {printf("%d\n",x%3);x/=3;}
        printf("--------------\n");
    }
    void gao(int now,int sr,int tot){
        int i;
        if(sr>=m-1){
          //  printf("j=%d now=%d\n",j,now);
          //  print(now);
            if(!d[cur][now]){
                state[cur][cnt[cur]++]=now;
            }
            d[cur][now]=max(d[cur][now],tot);
            return;
        }
        gao(now,m,tot);
        if(sr<=m-2){
            for(i=sr;i<=m-2;++i){
                if(b[i]==0 && b[i+1]==0 && mat[i][j]==0 && mat[i+1][j]==0){
                  //  printf("i=%d\n",i);
                    mat[i][j]=mat[i+1][j]=1;
                    gao(now+2*p[i]+2*p[i+1],sr+2,tot+1);
                    mat[i][j]=mat[i+1][j]=0;
                }
            }
        }
        if(sr<=m-3){
            for(i=sr;i<=m-3;++i){
                if(b[i]<2 && b[i+1]<2 && b[i+2]<2 && mat[i][j]==0 && mat[i+1][j]==0 && mat[i+2][j]==0){
                  //  printf("ii=%d\n",i);
                    mat[i][j]=mat[i+1][j]=mat[i+2][j]=1;
                    gao(now+2*p[i]+2*p[i+1]+2*p[i+2],sr+3,tot+1);
                    mat[i][j]=mat[i+1][j]=mat[i+2][j]=0;
                }
            }
        }
    }
    int main(){
       // freopen("test.in","r",stdin);
      //  freopen("test.out","w",stdout);
        int i,now,just,k,r,c,T;
        p[0]=1;
        for(i=1;i<10;++i) p[i]=p[i-1]*3;
        scanf("%d",&T);
        while(T--){
            scanf("%d%d%d",&n,&m,&k);
            memset(mat,0,sizeof(mat));
            memset(d,0,sizeof(d));
            while(k--){
                scanf("%d%d",&c,&r);
                mat[r-1][c-1]=1;
            }
            now=0;
            for(i=0;i<m;++i){
                now+=p[i];
                if(mat[i][0]) now+=p[i];
            }
            state[0][0]=now;
            cnt[0]=1;
            cur=0;
            ans=0;
            for(j=1;j<n;++j){
                pre=cur;
                cur=1-pre;
                cnt[cur]=0;
                memset(d[cur],0,sizeof(d[cur]));
                for(i=0;i<cnt[pre];++i){
                    just=state[pre][i];
                    for(k=0;k<m;++k){
                        b[k]=just%3;
                        just/=3;
                    }
                    now=0;
                    for(k=0;k<m;++k){
                        if(mat[k][j]){
                            now+=2*p[k];
                        }else if(b[k]==2){
                            now+=p[k];
                        }
                    }
                    gao(now,0,d[pre][state[pre][i]]);
                }
            }
            for(i=0;i<cnt[cur];++i)
                ans=max(ans,d[cur][state[cur][i]]);
            printf("%d\n",ans);
        }
        return 0;
    }

抱歉!评论已关闭.