您的位置:首页 > 其它

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

2016-10-16 12:02 417 查看

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
;
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+Sn≥0,其中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,j−1

好像意思改变了。。不过不影响我们敲程序。。。

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
, p
, dp

;

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;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: