zoukankan      html  css  js  c++  java
  • bzoj [SDOI2009]学校食堂Dining

    感觉这个状压dp比较难想。。

    dp[ i ][ s ][ k ] 表示前i - 1个都排好了, 从i开始的7个的取没取的状态为s, 且最后一个相对i的位置为k的最少花费。

    状态转移方程

    if(s & 1) dp[ i + 1][s >> 1][ k - 1] = min(dp[ i + 1][s >> 1][ k - 1], dp[ i ][ s ][ k ])

    else dp[ i ][ s ^ (1 << j)][ j ] = min(dp[ i ][ s ^ (1 << j) ][ j ], dp[ i ][ s ][ k ]) 

    转移的时候注意,限制条件。

    #include<bits/stdc++.h>
    #define LL long long
    #define fi first
    #define se second
    #define mk make_pair
    #define pii pair<int,int>
    #define piii pair<int, pair<int,int> >
    
    using namespace std;
    
    const int N = 1000 + 10;
    const int M = 10 + 7;
    const int inf = 0x3f3f3f3f;
    const LL INF = 0x3f3f3f3f3f3f3f3f;
    const int mod = 1e9 + 7;
    const int MOD = 1e6 + 3;
    const double eps = 1e-6;
    const int base = 8;
    
    pii a[N];
    int n, T, cost[N][N];
    int dp[N][1 << 8][16];
    int main() {
        scanf("%d", &T);
        while(T--) {
            memset(dp, inf, sizeof(dp));
            scanf("%d", &n);
            for(int i = 1; i <= n; i++) {
                scanf("%d%d", &a[i].fi, &a[i].se);
                a[i].se = min(a[i].se, n - i);
            }
    
            for(int i = 1; i <= n; i++) {
                for(int j = 1; j <= n; j++) {
                    if(i == j) continue;
                    cost[i][j] = a[i].fi ^ a[j].fi;
                }
            }
    
            dp[1][0][-1 + base] = 0;
    
            int up = 1 << 8;
            for(int i = 1; i <= n; i++) {
                for(int s = 0; s < up; s++) {
                    for(int k = -8; k <= 7; k++) {
                        if(dp[i][s][k + base] >= inf) continue;
                        if(s & 1) {
                            int t = s >> 1;
                            dp[i + 1][t][k - 1 + base] = min(dp[i + 1][t][k - 1 + base], dp[i][s][k + base]);
                        } else {
                            int last = inf;
                            for(int j = 0; j <= 7; j++) {
                                if(s & (1 << j)) continue;
    
                                if(i + j > last) break;
                                last = min(last, i + a[i + j].se + j);
                                int t = s ^ (1 << j);
                                dp[i][t][j + base] = min(dp[i][t][j + base], dp[i][s][k + base] + cost[i + k][i + j]);
                            }
                        }
                    }
                }
            }
    
            int ans = inf;
            for(int k = -8; k <= -1; k++)
                ans = min(ans, dp[n + 1][0][k + base]);
    
            printf("%d
    ", ans);
        }
        return 0;
    }
    /*
    */
  • 相关阅读:
    python函数的基本语法<三>
    python函数的基本语法<二>
    python中文件的基础操作
    python模块——configparser
    python模块——psutil
    python中程序的异常处理
    python——协程
    hbuilder 开发app 自动升级
    C# datagridview 这是滚动条位置
    C# 小知识点记录
  • 原文地址:https://www.cnblogs.com/CJLHY/p/9122988.html
Copyright © 2011-2022 走看看