CodeForces #?(727A|727B|727D|727F)|贪心|动态规划

727A

题目大意:给出s和t,对s有2个操作:一个×2,一个*10+1,问怎么操作能使s变成t。
题解:暴力。。

#include <cstdio>
typedef long long ll;
bool isPower2(ll x) {
    return x - (x & -x) == 0;
}

ll s, t, p[64];
void output(int d, ll r) {
    puts("YES"); int i;
    for (; r > 1; ++d)
        p[d + 1] = p[d] * 2, r /= 2;
    printf("%d\n", d);
    for (i = 1; i <= d; ++i)
        printf("%I64d ", p[i]);
}

int dfs(ll x, int d) {
    if (x > t) return 0;
    p[d] = x;
    if (t % x == 0 && isPower2(t / x)) return output(d, t / x), 1;
    if (dfs(x * 10 + 1, d + 1)) return 1;
    if (dfs(x * 2, d + 1)) return 1;
    return 0;
}

int main() {
    scanf("%I64d%I64d", &s, &t);
    if (!dfs(s, 1)) puts("NO");
    return 0;
}

727B

题目大意:给出含有字母与数字的字符串,其中数字有格式要求:从小数点往左起每3位要一个点分隔(但是一般习惯不都是逗号么。。)然后如果是整数不能有小数点。比如1.00是不合法的。问字符串里的数字和为多少(按格式输出)
题解:先挑出数字,然后去掉分隔点,但是如果不去掉小数点会有精度问题好奇怪。。然后乘个100去掉小数点最后按格式输出即可。
好奇怪stringstream转”10000.11”变成10000.13。。下次要好好注意sstream,切不可使用小数转换。。

#include <cstdio>
#include <iostream>
#include <string>
#include <sstream>
#include <iomanip>
using namespace std;
char s[1024];
string num;
int main() {
    int i; long long ans = 0, tmp;
    scanf("%s", s);
    for (i = 0; s[i]; ++i)
        if ('a' <= s[i] && s[i] <= 'z')
            s[i] = ' ';
    stringstream ss, tr; ss << s;
    tr.setf(ios::fixed, ios::floatfield);
    tr.precision(2);
    while (ss >> num) {
        while (1) {
            size_t idx = num.find('.');
            if (idx == string::npos)
                num = num + "00";
            if (idx == num.length() - 3)
                num = num.erase(idx, 1), idx = string::npos;
            if (idx == string::npos) {
                tr.clear();
                tr << num; tr >> tmp;
                ans += tmp;
                break;
            }
            num = num.erase(idx, 1);
        }
    }
    tr.clear();
    tr << ans * 0.01;
    tr >> num;
    int idx = num.find('.');
    for (idx -= 3; idx > 0; idx -= 3)
        num.insert(idx, ".");
    int l = num.length();
    if (l > 3 && num[l - 1] == '0' && num[l - 2] == '0' && num[l - 3] == '.')
        num.erase(l - 3);
    cout<<num;
    return 0;
}

727D

题目大意:有6款尺寸的衣服,每个人会想要其中的一款或相邻尺寸的2款衣服中的一种一款,问是否存在衣服的分配方案。
题解:首先只要一款的就先处理掉,2款的由于尺寸相邻,因此考虑按较小的那个尺寸进行排序,先试小的尺寸,没有就试大的,大的也没有就NO了。

#include <cstring>
#include <algorithm>
#include <vector>
#define rep(i,j,k) for(i=j;i<k;++i)
using namespace std;
const int N = 100005;
const char shirt[6][5] = {"S", "M", "L", "XL", "XXL", "XXXL"};
int getId(const char *s) {
    if (s[0] == 'S') return 0;
    if (s[0] == 'M') return 1;
    if (s[0] == 'L') return 2;
    if (s[1] == 'L') return 3;
    if (s[2] == 'L') return 4;
    if (s[3] == 'L') return 5;
}

int num[8], take[N];
char a[16], b[16], c[16];
vector<pair<int, int> > req;
int main() {
    int i, j, n;
    rep(i,0,6) scanf("%d", num + i);
    scanf("%d", &n);
    rep(i,0,n) {
        scanf("%s", c);
        for(j = 0; c[j]; ++j) if (c[j] == ',') { c[j] = ' '; break; }
        int ret = sscanf(c, "%s%s", a, b), id = getId(a);
        if (ret == 1) --num[take[i] = id];
        else req.push_back(make_pair(id, i));
    }
    sort(req.begin(), req.end());
    rep(i,0,req.size())
        if (num[req[i].first]) --num[req[i].first], take[req[i].second] = req[i].first;
        else if (req[i].first == 5 || !num[req[i].first + 1]) return puts("NO"), 0;
        else --num[req[i].first + 1], take[req[i].second] = req[i].first + 1;
    puts("YES");
    rep(i,0,n) puts(shirt[take[i]]);
    return 0;
}

727F

题目大意

有一个数列 {an} ,删除最少数量的元素使 n[1,750],qi+Sn0 ,其中 qi(0<i<m=200000)

题解

我们先进行预处理,令 fi,j 表示 i..n 段最多删去j个元素能满足的最小 q ,其实就是Si..n的最小值的相反数。很显然这里q越大,j越少。所以这里我们求出 fi,j 后对 fi 二分查找就可以找出最小q。

fi,j=max{fi+1,j+aifi+1,j1

好像意思改变了。。不过不影响我们敲程序。。。
http://codeforces.com/contest/727/submission/21456042
http://codeforces.com/contest/727/submission/21472657

#include <cstdio>
#include <algorithm>
using namespace std;
#define FOR(i,j,k) for(i=j;i<=k;++i)
#define FORD(i,j,k) for(i=j;i>=k;--i)
const int N = 1024;
int n, m;
int a[N], p[N], dp[N][N];

int main() {
    int i, j, q, k;
    scanf("%d%d", &n, &m);
    FOR(i,1,n) scanf("%d", a + i);
    FORD(i,n,1) {
        FOR(j,0,n) {
            dp[i][j] = dp[i + 1][j] + a[i];
            if (j > 0) dp[i][j] = max(dp[i][j], dp[i + 1][j - 1]);
        k = 0x8000000;
        FOR(j,0,n) if (dp[i][j] > k) k = dp[i][j], p[i] = j;
    }
    while (m--) {
        scanf("%d", &q);
        printf("%d\n", lower_bound(dp[i], dp[i] + 1 + p[i], -q) - dp[i]);
    }

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值