浙江十套 - 第八套 - 解题报告

  1. 产品报告
    对于B[i]降序排列是显而易见的,因为将最大的冷却时间放在最后,才会是最优的。这道DP反正当时我并没有做出来,以为是一个贪心。
    使用DP的原因是冷却时间在第一个机器和在第二个机器的分配不同,导致最后的答案不同。
    f[i][j] 表示第一个机器在处理前i个产品花费j时间时,总的时间花费的最小值。(f[i][j]包括了最后的冷却时间) , 所以第二个机器的花费可以算出来,总的花费就是上面两个取最小值。
    对于第一台机子:f[i][j] = min( f[i][j], max(f[i - 1][j - a[i]],,j + b[i] ), (如果上一个的冷却时间超级长,就是第一个,否则是第二个)对于第二台机子 : f[i][j] = min ( f[i][j], max( f[i - 1][j] , sum[i] - j + b[i])(i 位不由第一台机子处理因此是f[i - 1][j],剩下的由第二台处理)。
#include <cstdio>
#include <algorithm>
#include <cstring>
#define LOCAL
const int maxn = 210;
int n;
int sum[maxn], f[maxn][maxn * maxn];
int max (int x, int y) {
    return x > y ? x : y;
}

int min (int x, int y) {
    return x < y ? x : y;
}

struct Product {
    int a, b;
};
Product pro[maxn];

bool cmp (Product pro1, Product pro2) {
    return pro1.b > pro2.b;
}

inline void DP() {
    for (int i = 0; i <= n; ++ i)
        for (int j = 0; j <= maxn * maxn - 1; ++ j)
            f[i][j] = maxn * maxn + 10;
    f[0][0] = 0;

    for (int i = 1; i <= n; ++ i) {
        for (int j = 0; j <= sum[i]; ++ j) {
            if (j >= pro[i].a) {
                f[i][j] = min(f[i][j], max(f[i - 1][j - pro[i].a], j + pro[i].b));
            }
            if (sum[i] - j + pro[i].b >= 0) {
                f[i][j] = min(f[i][j], max(f[i - 1][j], sum[i] - j + pro[i].b));
            }
        }
    }
    
    int ans = 0x7fffffff - 1;
    for (int i = 1; i <= sum[n]; ++ i) {
        ans = min(f[n][i], ans);
    }
    printf("%d\n", ans);
}

inline void init() {
#ifdef LOCAL
    freopen("sort.in","r",stdin);
    freopen("sort.out","w",stdout);
#endif
    scanf("%d", &n);
    for (int i = 1; i <= n; ++ i) {
        scanf("%d%d", &pro[i].a, &pro[i].b);
    }
    std::sort(pro + 1, pro + n + 1, cmp);
    for (int i = 1; i <= n; ++ i)
        sum[i] = sum[i - 1] + pro[i].a;
}

int main() {
    init();
    DP();
    return 0;
}

2.分球
这道题非常简单,要么用数学方法算一下排列组合,要么就自己打一个递推,只是需要用高精度。

#include <cstdio>
#include <iostream>
#include <cstring>
using namespace std;

const int maxn = 110;
const int maxm = 100;
int n,m;
struct Bignum {
    int dig[maxn];
    int len;
    Bignum() {
        memset(dig,0,sizeof(dig));
        len = 1;
    }
};
Bignum F[maxn][maxn];
inline Bignum Plus(Bignum a, Bignum b) {
    for (int i = 1; i <= b.len; ++ i) {
        a.dig[i] += b.dig[i];   
    }
    for (int i = 1; i <= max(a.len,b.len) + 1; ++ i) {
        a.dig[i + 1] += a.dig[i] / 10;
        a.dig[i] %= 10;
    }
    int k = maxm - 1;
    while(a.dig[k] == 0) k --;
    a.len = k;
    return a;
}

inline Bignum Mul(Bignum a, int b) {
    for (int i = 1; i <= a.len; ++ i) {
        a.dig[i] *= b;
    }
    for (int i = 1; i <= maxm - 3; ++ i) {
        a.dig[i + 1] += a.dig[i] / 10;
        a.dig[i] %= 10;
    }
    int k = maxm - 1;
    while(a.dig[k] == 0) k --;
    a.len = k;
    return a;
}

inline void Print(Bignum a) {
    for (int i = a.len; i >= 1; -- i) {
        cout << a.dig[i];
    }
    putchar('\n');
}

inline void solve() {
    for (int i = 1; i <= maxn - 1; ++ i) {
        for (int j = 1; j <= maxn - 1; ++ j) {
            if ( i == j ) F[i][j].dig[1] = 1, F[i][j].len = 1;
            else if ( i > j ) {
                F[i][j] = Plus(Mul(F[i - 1][j],j),F[i - 1][j - 1]);
            }
        }
    }
}

int main() {
    freopen("ball.in","r",stdin);
    freopen("ball.out","w",stdout);
    int N,M;
    F[0][0].dig[1] = 1, F[0][0].len = 1;
    solve();
    while(cin >> N >> M) {
        if (N < M) cout << 0 << endl;
        else if (N == M) cout << 1 << endl;
        else Print(F[N][M]);
    }

}

3.地图
水得恐怖的一道题,主要是dfs标记同一条大陆上的,dfs时建立坐标变化数组要方便写一点。

#include <cstdio>
#include <iostream>
using namespace std;

const int maxn = 1010;
bool map[maxn][maxn];
int ans = 0;
int n,m;

int dx[5] = {0,1,-1,0,0};
int dy[5] = {0,0,0,1,-1};

inline void DFS(int x, int y) {
    map[x][y] = 0;
    for (int i = 1; i <= 4; ++ i) {
        int nowx = x + dx[i];
        int nowy = y + dy[i];
        if (map[nowx][nowy]){
            DFS(nowx,nowy);
        }
    }
}

int main() {
    freopen("map.in","r",stdin);
    freopen("map.out","w",stdout);
    cin >> n >> m;
    for (int i = 1; i <= n ; ++ i) {
        for (int j = 1; j <= m; ++ j) {
            char x;
            cin >> x;
            if(x == 'X') map[i][j] = 1;
            else map[i][j] = 0;
        }
    }

    for (int i = 1; i <= n; ++ i) {
        for (int j = 1; j <= m; ++ j) {
            if(map[i][j]) {
                DFS(i,j);
                ans ++;
            }
        }
    }
    cout << ans;
}

4.坐标变换
这道题要用到Graham的一点知识,还有关于凸包的一点小小的常识,用dp求出每一个点,就OK了。新建的n + 1 这个点是为了保证最后围成封闭。
然后感谢lcc大佬的帮助。

#include <cstdio>
#include <algorithm>
#define LOCAL
const int maxn = 105;
int f[maxn][maxn];

struct Point {
    int x, y;
};
Point map[maxn];

int n, ans = 0;

int max (int a, int b) {
    return a > b ? a : b;
}

bool cmp (Point a, Point b) {
    return ((double) a.y / a.x) < ((double) b.y / b.x);
}

inline bool check(int a, int b, int c) {
    int tmp = 0;
    tmp += map[a].x * map[b].y;
    tmp += map[a].y * map[c].x;
    tmp += map[b].x * map[c].y;
    tmp -= map[b].y * map[c].x;
    tmp -= map[c].y * map[a].x;
    tmp -= map[b].x * map[a].y;
    return tmp < 0; 
}

inline void init() {
#ifdef LOCAL
    freopen("polygon.in","r",stdin);
    freopen("polygon.out","w",stdout);
#endif
    scanf("%d", &n);
    for (int i = 1; i <= n; ++ i) {
        scanf("%d%d", &map[i].x, &map[i].y);
        f[i][0] = 1;
    }
    std::sort(map + 1, map + n + 1, cmp);
    map[0].x = 0, map[0].y = 0;
    map[n + 1].x = map[n + 1].y = 0;
}

inline void DP() {
    for (int i = 2; i <= n + 1; ++ i) {
        for (int j = 1; j < i; ++ j) {
            f[i][j] = 0;
            for (int k = 0; k < j; ++ k) {
                if (check(i, j, k)) {
                    f[i][j] = max(f[i][j], f[j][k] + 1);
                }
            }
        }
    }
    ans = 0;
    for (int i = 1; i <= n; ++ i) {
        ans = max(ans, f[n + 1][i]);
    }
    printf("%d\n", ans);
}

int main() {
    init();
    DP();
}

猜你喜欢

转载自www.cnblogs.com/Alessandro/p/9147129.html
今日推荐