A 吐泡泡
链接:https://www.nowcoder.com/acm/contest/74/A
来源:牛客网
题目描述
小鱼儿吐泡泡,嘟嘟嘟冒出来。小鱼儿会吐出两种泡泡:大泡泡”O”,小泡泡”o”。
两个相邻的小泡泡会融成一个大泡泡,两个相邻的大泡泡会爆掉。
(是的你没看错,小气泡和大气泡不会产生任何变化的,原因我也不知道。)
例如:ooOOoooO经过一段时间以后会变成oO。
输入描述:
数据有多组,处理到文件结束。
每组输入包含一行仅有’O’与’o’组成的字符串。
输出描述:
每组输出仅包含一行,输出一行字符串代表小鱼儿吐出的泡泡经过融合以后所剩余的泡泡。
示例1
输入
ooOOoooO
输出
oO
说明
自左到右进行合并
备注:
对于100%的数据,
字符串的长度不超过100。
分析:
注意题意,泡泡的结合仅一个过程自左向右,一个栈的操作就可以了,写栈时一定注意栈空状态。。。
#include <cstdio>
#include <algorithm>
#include <cstring>
#include <cmath>
#include <stack>
using namespace std;
typedef long long LL;
const int mod = 24 * 60;
const int MAXN = 1e2 + 10;
char str[MAXN], ch[MAXN];
int main() {
while(~scanf("%s", str)) {
int p = 0, len = strlen(str);
str[len] = 0;
stack<char> s;
for(int i = 0; i < len; i++) {
if(str[i] == 'o') {
if(s.empty()) s.push('o');
else if(s.top() == 'o') {
s.pop();
if(s.empty()) s.push('O'); //注意所有的栈空状态
else if(s.top() == 'O') s.pop();
else s.push('O');
}
else s.push('o');
}
else {
if(s.empty()) s.push('O');
else if(s.top() == 'O') s.pop();
else s.push('O');
}
}
while(!s.empty()) {
ch[p++] = s.top();
s.pop();
}
for(int i = p - 1; i >= 0; i--) {
printf("%c", ch[i]);
}
printf("\n");
}
return 0;
}
B TaoTao要吃鸡
链接:https://www.nowcoder.com/acm/contest/74/B
来源:牛客网
题目描述
Taotao的电脑带不动绝地求生,所以taotao只能去玩pc版的荒野行动了,
和绝地求生一样,游戏人物本身可以携带一定重量m的物品,装备背包
之后可以多携带h(h为0代表没有装备背包)重量的东西。玩了几天
taotao发现了一个BUG,当装备背包之后,如果可携带重量没有满,就
可以拿一个任意重的东西。(解释看样例)有一天taotao空降到了一个
奇怪的岛上,岛上有n件装备,每个装备都有重量Wi和威力值Vi,但taotao
不认识这些装备,所以他来求助你,挑选威力最大的装备,帮助他吃鸡。
输入描述:
本题有多组输入(小于10),当n=0时结束输入。
第一行输入n,m,h。n,m,h为整数,并且0<=n,m,h<=100,
接下来n行,每行输入第i个物品的物品的重量Wi和威力值Vi。0<=Wi,Vi<=100.
输出描述:
输出最大威力值,每组输出一行。
示例1
输入
3 3 3
2 3
3 2
2 3
0
输出
8
说明
可携带的总重量为6,当拿了前两件装备,此时容量为5/6,还可以再拿第三件物品。
分析:
注意读题,当有
h!=0
h
!
=
0
的时候,才会出现bug。数据范围很小,xjb搞就行。可以枚举不拿的那一件物品,其余的用01背包处理,就可以了。
我试了一下把最大vi的物品贪心出来,尽然过了,数据好水。。。
#include <cstdio>
#include <algorithm>
#include <cstring>
#include <cmath>
#include <stack>
using namespace std;
typedef long long LL;
const int MAXN = 110;
int w[MAXN], v[MAXN], dp[MAXN << 2];
int main() {
int n, m, h;
while(scanf("%d", &n) && n) {
scanf("%d %d", &m, &h);
m += h;
for(int i = 0; i < n; i++) {
scanf("%d %d", &w[i], &v[i]);
}
int ans = 0;
memset(dp, 0, sizeof(dp));
for(int i = 0; i < n; i++) {
for(int j = m; j >= w[i]; j--) {
dp[j] = max(dp[j], dp[j - w[i]] + v[i]);
ans = max(ans, dp[j]);
}
}
if(!h) {
printf("%d\n", ans);
continue;
}
for(int p = 0; p < n; p++) { //枚举不能拿的每一件物品
memset(dp, 0, sizeof(dp));
for(int i = 0; i < n; i++) {
if(i == p) continue;
for(int j = m; j >= w[i]; j--) {
dp[j] = max(dp[j], dp[j - w[i]] + v[i]);
}
}
int cnt = dp[m];
for(int i = 0; i < m; i++) {
cnt = max(cnt, dp[i] + v[p]);
}
ans = max(ans, cnt);
}
printf("%d\n", ans);
}
}
贪心写法,数据水,是可以hack掉的。。。
2 2 2
5 1
2 3
输出:4
#include <cstdio>
#include <algorithm>
#include <cstring>
#include <cmath>
#include <stack>
using namespace std;
typedef long long LL;
const int MAXN = 110;
int w[MAXN], v[MAXN], dp[MAXN << 2];
int main() {
int n, m, h;
while(scanf("%d", &n) && n) {
memset(dp, 0, sizeof(dp));
scanf("%d %d", &m, &h);
m += h;
int ans = 0, res = 1e6, id, ant = 0;
for(int i = 0; i < n; i++) {
scanf("%d %d", &w[i], &v[i]);
if(v[i] >= ant) { //贪心最大vi
ant = v[i];
if(w[i] < res) {
id = i;
}
}
}
for(int i = 0; i < n; i++) {
for(int j = m; j >= w[i]; j--) {
dp[j] = max(dp[j], dp[j - w[i]] + v[i]);
ans = max(ans, dp[j]);
}
}
if(!h) {
printf("%d\n", ans);
continue;
}
memset(dp, 0, sizeof(dp));
for(int i = 0; i < n; i++) {
if(i == id) continue;
for(int j = m; j >= w[i]; j--) {
dp[j] = max(dp[j], dp[j - w[i]] + v[i]);
}
}
int cnt = max(dp[m], ans);
for(int i = 0; i < m; i++) {
cnt = max(cnt, dp[i] + ant);
}
printf("%d\n", cnt);
}
}
D YB要打炉石
链接:https://www.nowcoder.com/acm/contest/74/D
来源:牛客网
题目描述
Wozuinb非常喜欢打炉石传说,但是菜的不行,所以他决定打
竞技场来练练手。系统按顺序给出n张卡牌,每张卡牌都有自
己的使用消耗a[i],每次只给出一张,wozuinb可以选择或者
弃掉这张牌。每选择一张牌都会按选择顺序放在卡槽中,当
卡槽中放满30张即可组成一套套牌。Wozuinb希望自己的套牌的
消耗满足一个平滑的曲线,即30张卡牌都满足第i张卡牌的消耗
不小于第i-1张(i>1)。请你帮助wozuinb看一看,这些卡牌能不
能组成想要的套牌,如果能组成输出“yes”,如果不能输出“no”。
输入描述:
第一行输入一个整数n, 0<n<100 0 < n < 100 。
第二行输入一行数字a[i],每个数字用空格隔开,代表第i张出现的卡牌的消耗。
输出描述:
输出一行,“yes”或“no”
示例1
输入
5
1 2 3 4 5
输出
no
分析
非严格最长递增子序列,O(nlogn)过的;
#include <cstdio>
#include <algorithm>
#include <cstring>
#include <cmath>
#include <stack>
using namespace std;
typedef long long LL;
const int mod = 24 * 60;
const int MAXN = 1e2 + 10;
int dp[MAXN], arr[MAXN];
int main() {
int n;
scanf("%d", &n);
for(int i = 1; i <= n; i++) {
scanf("%d", &arr[i]);
}
dp[1] = arr[1];
int p = 2;
for(int i = 2; i <= n; i++) {
int id = upper_bound(dp + 1, dp + p, arr[i]) - dp;
if(id == p || arr[i] >= dp[p - 1]) dp[p++] = arr[i];
else {
dp[id] = arr[i];
}
}
if(p > 30) puts("yes");
else puts("no");
return 0;
}
/*
30
2 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30
*/
E 小G有一个大树
链接:https://www.nowcoder.com/acm/contest/74/E
来源:牛客网
题目描述
小G想要把自己家院子里的橘子树搬到家门口(QAQ。。就当小G是大力水手吧)
可是小G是个平衡性灰常灰常差的人,他想找到一个这个橘子树的平衡点。
怎么描述这棵树呢。。。就把它看成由一个个节点构成的树吧。结点数就
代表树重。
输入描述:
多组数据输入输出,
第一行包含一个整数n(3<=n<=1000)代表树的结点的个数
以下n-1行描述(1-n)节点间的连接关系。
输出描述:
输出两个个整数 x,num 分别代表树的平衡点,和删除平衡点后最大子树的结点数(如果结点数相同输出编号小的)。
示例1
输入
3
1 2
1 3
输出
1 1
分析:
裸的树重心,直接暴力,没用树形dp;
#include <cstdio>
#include <algorithm>
#include <cstring>
#include <cmath>
#include <vector>
using namespace std;
typedef long long LL;
const int MAXN = 1010;
int dp[MAXN][MAXN];
vector<int> G[MAXN];
int ans, n, x, y;
inline void init() {
for(int i = 0; i < MAXN; i++) {
G[i].clear();
}
}
inline void dfs(int u, int cnt) {
for(int i = 0; i < G[u].size(); i++) {
int v = G[u][i];
if(v == cnt) continue;
ans++;
dfs(v, u);
}
}
int main() {
while(scanf("%d", &n) != EOF) {
init();
for(int i = 1; i < n; i++) {
scanf("%d%d", &x, &y);
G[x].push_back(y);
G[y].push_back(x);
}
int sum1 = MAXN, sum2 = MAXN * MAXN; //节点和编号
for(int i = 1; i <= n; i++) {
int cnt1 = 0;
for(int j = 0; j < G[i].size(); j++) {
ans = 1;
dfs(G[i][j], i);
cnt1 = max(cnt1, ans);
}
if(sum1 > cnt1) {
sum1 = cnt1;
sum2 = i;
}
}
printf("%d %d\n", sum2, sum1);
}
return 0;
}
F 德玛西亚万岁
链接:https://www.nowcoder.com/acm/contest/74/F
来源:牛客网
题目描述
德玛西亚是一个实力雄厚、奉公守法的国家,有着功勋卓著的光荣军史。
这里非常重视正义、荣耀、职责的意识形态,这里的人民为此感到强烈自豪。
有一天他们想去制裁邪恶的比尔吉沃特,于是派遣了自己最优秀的战士。
结果比尔吉沃特领土太小,只有长为n宽为m共计n*m块土地,其中有些土
地标记为0表示为高山峻岭或者深海湖泊,英雄们无法在其中站立,只有标
记为1的土地才能容纳一个英雄。德玛西亚的英雄们战斗时有一个特点,他
们不希望队友站在自己旁边显得很暧昧。请问最多能有多少种安排德玛西
亚英雄的方法?
输入描述:
输入包含多组测试数据;
每组数据的第一行包含2个整数n和m (n <= 12, m <= 12 ),之间用空格隔开;
接下来的n行,每行m个数,表示n*m的比尔吉沃特领土。
输出描述:
输出一个整数n代表安排应用的方法。
(答案取膜100000000)
示例1
输入
3 3
1 1 1
0 1 1
1 0 0
输出
24
分析:
dp[i][j]:第i种状态在第j行的方案数,dp[p][i]=dp[p][i]+dp[j][i−1]
d
p
[
i
]
[
j
]
:
第
i
种
状
态
在
第
j
行
的
方
案
数
,
d
p
[
p
]
[
i
]
=
d
p
[
p
]
[
i
]
+
d
p
[
j
]
[
i
−
1
]
;
vis[i]:表示第i种的状态;
v
i
s
[
i
]
:
表
示
第
i
种
的
状
态
;
把满足的状态先预处理状压出来,把网格可填的位置二进制表示,然后把这些状态按行填进去,和可填的二进制再进行与运算。初始化第一行,然后暴力第
i
i
行和第行状态,O(
224∗12
2
24
∗
12
) ;
#include <cstdio>
#include <algorithm>
#include <cstring>
#include <cmath>
#include <stack>
using namespace std;
const int mod = 1e8;
const int MAXN = 15;
int arr[MAXN], dp[2 << 13][MAXN], vis[2 << 13];
inline void dfs_DP(int &res, int m) {
for(int i = 0; i < (1 << m); i++) {
if((i & (i << 1)) == 0) {
vis[res++] = i;
}
}
}
int main() {
int n, m;
while(scanf("%d %d", &n, &m) != EOF) {
memset(dp, 0, sizeof(dp));
memset(arr, 0, sizeof(arr));
memset(vis, 0, sizeof(vis));
int k, ans = 1;
dfs_DP(ans, m);
// printf("%d -> %d\n", ans, m);
for(int i = 1; i <= n; i++) {
for(int j = 0; j < m; j++) {
scanf("%d", &k);
if(!k) arr[i] += (1 << j);
}
}
for(int i = 1; i < ans; i++) {
if((arr[1] & vis[i]) == 0) {
dp[i][1] = 1;
}
}
for(int i = 2; i <= n; i++) {
for(int j = 1; j < ans; j++) {
for(int p = 1; p < ans; p++) {
int x = vis[j], y = vis[p];
if((x & y) || (y & arr[i])) continue;
dp[p][i] = (dp[p][i] + dp[j][i - 1]) % mod;
}
}
}
int sum = 0;
for(int i = 1; i < ans; i++) {
sum = (sum + dp[i][n]) % mod;
}
printf("%d\n", sum % mod);
}
}
G 送分了QAQ
链接:https://www.nowcoder.com/acm/contest/74/G
来源:牛客网
题目描述
杭州人称傻乎乎的人为62,而嘟嘟家这里没有这样的习俗。
相比62,他那里的人更加讨厌数字38,当然啦,还有4这个
数字!所以啊,嘟嘟不点都不想见到包含38或者4的数字。
每次给出一个区间[n,m],你能找到所有令人讨厌的数字吗?
输入描述:
多组输入输出;
输入的都是整数对n、m (0<n≤m<1000000) ( 0 < n ≤ m < 1000000 ) ,
如果遇到都是0的整数对,则输入结束。
输出描述:
对于每次的输入
输出全部令人讨厌的数的个数
示例1
输入
1 100
0 0
输出
20
分析:
预处理区间和,或者数位dp解;
#include <cstdio>
#include <algorithm>
#include <cstring>
#include <cmath>
using namespace std;
typedef long long LL;
const int mod = 24 * 60;
const int MAXN = 1e6 + 10;
int dp[MAXN];
bool judge(int x) {
int ans = x, p = 0;
int arr[10];
while(ans) {
arr[p++] = ans % 10;
ans /= 10;
}
arr[p] = 0;
for(int i = 0; i < p; i++) {
if(arr[i] == 8 && arr[i + 1] == 3 || arr[i] == 4) return false;
}
return true;
}
void init() {
dp[0] = 0;
for(int i = 1; i <= MAXN - 5; i++) {
dp[i] += dp[i - 1];
if(!judge(i)) dp[i] += 1;
}
}
int main() {
int n, m;
init();
while(scanf("%d%d", &n, &m) && (n + m)) {
printf("%d\n", dp[m] - dp[n - 1]);
}
return 0;
}
H 了断局
链接:https://www.nowcoder.com/acm/contest/74/H
来源:牛客网
题目描述
既然是了断局了,大家就随便玩玩数字呗。
已知一个数列前10项分别是
{0, 1, 1, 2, 4, 7, 13, 24, 44, 81}
小G不满足呀:我要更多的数!!!不给就不让你们玩了。
小G会问你第n项是什么数字,请回答这个顽皮的孩子吧。
输入描述:
多组数据输入输出;
第一行输入一个整数n(1<=n<=50)
输出描述:
输出数列中的第n个数。
示例1
输入
1
2
3
输出
0
1
1
分析:
初项题目中给出,一眼递推式:
dp[i]=dp[i−1]+dp[i−2]+dp[i−3]
d
p
[
i
]
=
d
p
[
i
−
1
]
+
d
p
[
i
−
2
]
+
d
p
[
i
−
3
]
;
#include <cstdio>
#include <algorithm>
#include <cstring>
#include <cmath>
using namespace std;
typedef long long LL;
const int mod = 24 * 60;
const int MAXN = 1e6 + 10;
LL dp[55];
void init() {
dp[0] = 0;
dp[1] = dp[2] = 1;
for(int i = 3; i <= 50; i++) {
dp[i] = dp[i - 1] + dp[i - 2] + dp[i - 3];
}
}
int main() {
int n;
init();
while(scanf("%d", &n) != EOF) {
printf("%lld\n", dp[n - 1]);
}
return 0;
}