zoukankan      html  css  js  c++  java
  • CodeForces 1107 F Vasya and Endless Credits

    题目传送门

    题解:

    需要注意到的是 每个offer都获益都是会随着时间的增加而渐少(或不变)。

    所以我们可以知道,最多在第n个月的时候这个人会买车离开。

    solve1:最优2分图匹配

    我们可以把每个月都和每个offer建边。

    val[i][j]代表的是离开前倒数第i个月获取了第j个月的offer, 所以边权就是 max(0ll, a-min(j-1,k)*b).

    最后跑一遍km。

    所以复杂度是 n^3.

    代码:

     1 /*
     2 code by: zstu wxk
     3 time: 2019/02/02
     4 */
     5 #include<bits/stdc++.h>
     6 using namespace std;
     7 #define Fopen freopen("_in.txt","r",stdin); freopen("_out.txt","w",stdout);
     8 #define LL long long
     9 #define ULL unsigned LL
    10 #define fi first
    11 #define se second
    12 #define pb push_back
    13 #define lson l,m,rt<<1
    14 #define rson m+1,r,rt<<1|1
    15 #define lch(x) tr[x].son[0]
    16 #define rch(x) tr[x].son[1]
    17 #define max3(a,b,c) max(a,max(b,c))
    18 #define min3(a,b,c) min(a,min(b,c))
    19 typedef pair<int,int> pll;
    20 const int inf = 0x3f3f3f3f;
    21 const int _inf = 0xc0c0c0c0;
    22 const LL INF = 0x3f3f3f3f3f3f3f3f;
    23 const LL _INF = 0xc0c0c0c0c0c0c0c0;
    24 const LL mod =  (int)1e9+7;
    25 const int N = 510;
    26 int n;
    27 LL val[N][N];
    28 LL lx[N], ly[N], slack[N];
    29 int linky[N];
    30 LL pre[N];
    31 bool vis[N], visx[N], visy[N];
    32 void bfs(int k){
    33     LL px, py = 0,yy = 0, d;
    34     memset(pre, 0, sizeof(LL) * (n+2));
    35     memset(slack, inf, sizeof(LL) * (n+2));
    36     linky[py]=k;
    37     do{
    38         px = linky[py],d = INF, vis[py] = 1;
    39         for(int i = 1; i <= n; i++)
    40             if(!vis[i]){
    41                 if(slack[i] > lx[px] + ly[i] - val[px][i])
    42                     slack[i] = lx[px] + ly[i] -val[px][i], pre[i]=py;
    43                 if(slack[i]<d) d=slack[i],yy=i;
    44             }
    45         for(int i = 0; i <= n; i++)
    46             if(vis[i]) lx[linky[i]] -= d, ly[i] += d;
    47             else slack[i] -= d;
    48         py = yy;
    49     }while(linky[py]);
    50     while(py) linky[py] = linky[pre[py]] , py=pre[py];
    51 }
    52 void KM(){
    53     memset(lx, 0, sizeof lx);
    54     memset(ly, 0, sizeof ly);
    55     memset(linky, 0, sizeof(int)*(n+2));
    56     for(int i = 1; i <= n; i++)
    57         memset(vis, 0, sizeof(bool)*(n+2)), bfs(i);
    58 }
    59 void input(){
    60     scanf("%d", &n);
    61     LL a, b, k;
    62     for(int i = 1; i <= n; ++i){
    63         scanf("%I64d%I64d%I64d", &a, &b, &k);
    64         for(LL j = 0; j < n; ++j){
    65             val[i][j+1] = max(0ll, a-min(j,k)*b);
    66         }
    67     }
    68 }
    69 int main(){
    70     input();
    71     KM();
    72     LL ans = 0;
    73     for(int i = 1; i <= n; ++i)
    74         ans += lx[i] + ly[i];
    75     printf("%lld
    ", ans);
    76     return 0;
    77 }
    View Code

    solve2:DP

    首先需要明白一点,就是如果所有offer 还款的期限还没有到的话,那么肯定是bi越大的offer越后拿更优。

    所以把所有的offer按bi大小sort一下,大的排在前面。

    dp[i][j] 代表的是 处理到第i个物品, 倒数第j个月的花费是多少。

    所以,最显然的转移方式就是 dp[i][j] = max(dp[i][j], dp[i-1][j-1] + max(0ll, A[i].a - (j-1)*A[i].b)).

    还需要明白的一点就是,如果bi越大,理论上是放在越后拿越好,但是到如果完全还完贷款的那种offer,是越早拿越好,可以让别的offer少还一个月的贷款。

    所以又存在另一种转移方式 dp[i][j] = dp[i-1][j] + max(0ll, A[i].a - A[i].k*A[i].b);

    代码:

    /*
    code by: zstu wxk
    time: 2019/02/02
    */
    #include<bits/stdc++.h>
    using namespace std;
    #define Fopen freopen("_in.txt","r",stdin); freopen("_out.txt","w",stdout);
    #define LL long long
    #define ULL unsigned LL
    #define fi first
    #define se second
    #define pb push_back
    #define lson l,m,rt<<1
    #define rson m+1,r,rt<<1|1
    #define lch(x) tr[x].son[0]
    #define rch(x) tr[x].son[1]
    #define max3(a,b,c) max(a,max(b,c))
    #define min3(a,b,c) min(a,min(b,c))
    typedef pair<int,int> pll;
    const int inf = 0x3f3f3f3f;
    const int _inf = 0xc0c0c0c0;
    const LL INF = 0x3f3f3f3f3f3f3f3f;
    const LL _INF = 0xc0c0c0c0c0c0c0c0;
    const LL mod =  (int)1e9+7;
    const int N = 550;
    struct Node{
        LL a, b, k;
        bool operator<(const Node & x) const{
            return b > x.b;
        }
    }A[N];
    int n;
    LL dp[N][N];
    void Ac(){
        for(int i = 1; i <= n; ++i)
            scanf("%I64d%I64d%I64d", &A[i].a, &A[i].b, &A[i].k);
        sort(A+1, A+1+n);
        for(int i = 1; i <= n; ++i){
            for(int j = 0; j <= n; ++j){
                dp[i][j] = dp[i-1][j] + max(0ll, A[i].a - A[i].k*A[i].b);
                if(j) dp[i][j] = max(dp[i][j], dp[i-1][j-1] + max(0ll, A[i].a - (j-1)*A[i].b));
            }
        }
        LL ans = 0;
        for(int i = 0; i <= n; ++i)
            ans = max(ans, dp[n][i]);
        printf("%I64d
    ", ans);
    }
    int main(){
        while(~scanf("%d", &n)){
            Ac();
        }
        return 0;
    }
    View Code
  • 相关阅读:
    Conv2 GPU加速(有代码有图有真相)
    OpenACC指令适不适合我的程序吗?
    MongoDBHelper
    Js事件 事件绑定
    xslt元素 applyimports
    博客成立,开启一段追逐之旅,留个小小的纪念 ^^
    函数
    C语言基本特性
    预处理
    数组
  • 原文地址:https://www.cnblogs.com/MingSD/p/10349136.html
Copyright © 2011-2022 走看看