2018年8月12日头条笔试 A、B两人取卡片问题 - 动态规划

https://www.nowcoder.com/discuss/93316
动态规划

这里写图片描述


#include <bits/stdc++.h>
// https://www.nowcoder.com/question/next?pid=8537290&qid=141068&tid=17473994
using namespace std;
#define M(a, b) memset(a,b,sizeof(a))

// memset(a,0x3f,sizeof(a))
//memset(a,0xcf,sizeof(a))
typedef long long LL;

int myswap(int &x, int &y) {
    int a = x;
    x = y;
    y = a;
}


int main() {

    int n;
    cin >> n;
    vector<int> x(n + 1), y(n + 1);
    for (int i = 1; i <= n; i++) {
        cin >> x[i] >> y[i];
    }

    int sumx = accumulate(x.begin(), x.end(), 0);
    int sumy = accumulate(y.begin(), y.end(), 0);
    int INF = -sumy * 4;
    // 滚动数组, f[i][j] 定义取前i张卡片,A和B两人的差值为j时的团队最大分数值
    // 因为差值可能为负数,而数组下标不能为负数,所以加上 sumx 变为大于等于0的数,注意只需要在第33行第一轮加上sumx 即可,初始化为 INF
    vector<vector<int>> f(2, vector<int>(2 * sumx + 2, INF));
    int pre = 0, cur = 1;
    f[cur][sumx] = 0;

    int total = 2 * sumx + 2;
    for (int i = 1; i <= n; i++) {
        myswap(pre, cur);

        for (int j = 1; j <= 2 * sumx + 1; j++) {
            f[cur][j] = f[pre][j]; // 初始化,当前状态等于前一状态的值
        }

        for (int j = 1; j <= 2 * sumx + 1; j++) {
            if (j + x[i] < total) {
                //                j = j+x[i] (上一个状态的差值) - x[i] 当前状态的差值
                f[cur][j] = max(f[cur][j], f[pre][j + x[i]] + y[i]);
                printf("f[pre][j + x[i]] %d f[cur][j] %d \n", f[pre][j + x[i]], f[cur][j]);

            }

            if (j - x[i] >= 1) {
//                j = j-x[i] (上一个状态的差值) + x[i] 当前状态的差值
//                printf("f[pre][j + x[i]] %d \n", f[pre][j - x[i]]);

                f[cur][j] = max(f[cur][j], f[pre][j - x[i]] + y[i]);
                printf("f[pre][j + x[i]] %d f[cur][j] %d \n", f[pre][j + x[i]], f[cur][j]);


            }
        }
    }

    int ans = f[cur][sumx];
    cout << ans << endl;
//    cout<<f[cur][0]<<endl;


    return 0;
} 
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值