首页 > 其他分享 >P4928 [MtOI2018]衣服?身外之物! 题解

P4928 [MtOI2018]衣服?身外之物! 题解

时间:2022-12-26 13:13:34浏览次数:58  
标签:状态 return 衣服 int 题解 MtOI2018 res P4928 include

题意

gcd 共有 \(n\) 件衣服,编号为 \(A_1,A_2,\cdots A_n\)。

每一件衣服分别拥有颜色值和清洗时间,他在每一件衣服穿完以后都会将其送去清洗,而这件衣服当天所拥有的舒适感取决于当天的天气与他的衣服颜色值的乘积,天气值存在负数。

现给出共 \(m\) 天的天气情况,求最大舒适值。

分析

数据范围极小,考虑状压。

设当前状态为 \(f_{i, j}\) 表示已经过完了第 \(i\) 天,过完第 \(i\) 天之后的衣服状态为 \(j\)。其中 \(j\) 是一个 \(7\) 进制数,它的第 \(k\) 位表示第 \(k\) 件衣服还需要洗几天。(若 \(j = 0\),则表示不需要洗了,可以直接用。)

由于本人比较懒,因此直接用了十进制数代替七进制。(因此拿到了最劣解)。

总状态数最劣为 \(O(m \times \prod y_i)\) 个,在题目数据范围内可过。为了加速,可以提前处理出可用状态。

代码示例

#include <algorithm>
#include <iostream>
#include <cstring>
#include <cstdio>
#include <vector>
#include <cmath>
#define rep(i, a, b) for (int i = (a); i <= (b); i ++ )

using namespace std;

using LL = long long;
const int N = 2010;

int n, m;
int c[N], t[N], w[N];
LL f[N][7000];
vector<int> state;

int get(int x, int k) { // 取出 x 的第 k 位
    int res; while (k) res = x % 10, x /= 10, k -- ;
    return res;
}

bool check(int s) { // 判断状态 s 是否可用
    //  判断条件:1. 没有一位大于它最大的清洗时间
    //  2. 必须有至少以为是 0,否则 gcd 将没有衣服穿
    for (int i = 1; i <= n; i ++ ) if (get(s, i) > t[i]) return false;
    for (int i = 1; i <= n; i ++ ) if (!get(s, i)) return true;
    return false;
}

int modify(int s, int k) { // 改动 s 的第 k 位
    //  即:其他衣服的清洗时间 - 1,第 k 天的重置位 t[k]
    int ans = 0;
    for (int i = n; i; i -- )
        if (i == k) ans = ans * 10 + t[k];
        else ans = ans * 10 + (get(s, i) > 0 ? get(s, i) - 1 : 0);
    return ans;
}

int main() {
    scanf("%d%d", &n, &m);
    for (int i = 1; i <= n; i ++ )
        scanf("%d", &c[i]);
    for (int i = 1; i <= n; i ++ )
        scanf("%d", &t[i]);
    for (int i = 1; i <= m; i ++ )
        scanf("%d", &w[i]);
    
    for (int i = 0; i < pow(10, n); i ++ ) // 枚举可用状态
        if (check(i))
            state.push_back(i); // 并存储
	
    memset(f, -0x7f, sizeof f);
    f[0][0] = 0;
    for (int i = 0; i < m; i ++ )
        for (auto j : state)
            for (int k = 1; k <= n; k ++ )
                if (f[i][j] != -0x7f7f7f7f && !get(j, k))
                    f[i + 1][modify(j, k)] = max(f[i + 1][modify(j, k)], f[i][j] + w[i + 1] * c[k]);
    
    LL res = -0x7f7f7f7f;
    for (auto i : state)
        res = max(res, f[m][i]);
    if (res == -0x7f7f7f7f) puts("gcd loves her clothes!");
    else printf("%lld\n", res);

    return 0;
}

标签:状态,return,衣服,int,题解,MtOI2018,res,P4928,include
From: https://www.cnblogs.com/LcyRegister/p/17005562.html

相关文章

  • NSIS编辑时的乱码问题解决方法
    在Windows中文系统中,HMNISEdit下使用非中文和英文,比如韩文、日语或者阿拉伯语等。会发现编辑的文字变成乱码或者问号。     1、在安装的过程中显示乱码。2、......
  • AcWing291.蒙德里安的梦想题解
    题解:蒙德里安的梦想注:本题解内容简陋,多有不周,敬请谅解。如果有问题请在评论区留言。谢谢。由于作者能力有限,这篇题解不会给出太严谨的证明,只是旨在帮助大家更好地理解此......
  • AcWing83场周赛题解
    第一题、奇偶题目链接:https://www.acwing.com/activity/content/problem/content/7862/比较麻烦(本人做法)找出不同字符个数,再判断。#include<iostream>usingnamespac......
  • 洛谷P4146 序列终结者 题解 splay tree
    题目链接:https://www.luogu.com.cn/problem/P4146题目大意:支持:区间更新(+x)区间翻转区间查询(最大值)解题思路:几乎和AcWing2437.Splay这题一模一样。示例程序:#inc......
  • Codeforces 983 D Arkady and Rectangles 题解
    题目链接挺有意思的数据结构题,题面看着像个板子,其实还是有不少学问的。平面上一堆矩形的题目常见套路就是对\(x\)轴扫描线,\(y\)轴线段树维护,这题也不例外。我们先对坐标......
  • CF732D Exams 题解
    题目链接题目分析:首先可以发现,如果当前第\(i\)天可以完成所有考试,那么第\(i+1\)天一定也可以。因此,答案具有单调性。考虑二分,将原问题转换为判定性问题。判定是否......
  • AT_jag2018summer_day2_a 10^N+7 题解
    题目传送门题目大意有三个非负整数$x,y,z$,找到符合以下条件的最小非负整数\(n\);$n\{\rm\mod}\10^1+7\=\x$$n\{\rm\mod}\10^2+7\=\y$$n\{\rm\mo......
  • CF864C Bus 题解
    题目传送门题目大意一辆汽车从\(0\)到\(a\)往返\(k\div2\)次(也就是去算一次,回算一次);原来有\(b\)升油,每行驶一单位距离消耗一升油,在\(f\)有加油站(可以加满油......
  • UVA13197 Cuberoot This 题解
    题目传送门题目大意求满足\(x^3\bmodp=a\)且\(x<p\)的数\(x\),升序输出。解题思路在\(0\)到\(p-1\)的范围内,查找满足条件的\(x\);值得注意的是,输出要留意:最......
  • AT_joi2022_yo1a_d 箱と鍵 (Boxes and Keys) 题解
    题目传送门题目大意给定一个长度为\(n\)的数组\(a\)和一个长度为\(m\)的数组\(b\),求\(a\)中有多少个数在\(b\)中出现过。解题思路数据比较小,可以直接暴力:......