2018年全国多校算法寒假训练营练习比赛(第二场)

吐泡泡

时间限制:C/C++ 1秒,其他语言2秒

空间限制:C/C++ 32768K,其他语言65536K
64bit IO Format: %lld

题目描述 

小鱼儿吐泡泡,嘟嘟嘟冒出来。小鱼儿会吐出两种泡泡:大泡泡"O",小泡泡"o"。
两个相邻的小泡泡会融成一个大泡泡,两个相邻的大泡泡会爆掉。
(是的你没看错,小气泡和大气泡不会产生任何变化的,原因我也不知道。)
例如:ooOOoooO经过一段时间以后会变成oO。

输入描述:

数据有多组,处理到文件结束。
每组输入包含一行仅有'O'与'o'组成的字符串。

输出描述:

每组输出仅包含一行,输出一行字符串代表小鱼儿吐出的泡泡经过融合以后所剩余的泡泡。
示例1

输入

ooOOoooO

输出

oO

说明

自左到右进行合并

备注:

对于100%的数据,
字符串的长度不超过100。

#include <iostream>
#include <stdio.h>
#include <math.h>
#include <algorithm>
#include <string.h>
using namespace std;
typedef long long  LL;
const int maxn = 111;
int cnt[maxn];
int main()
{
	string s;

	while(cin>>s){
		int flag =1;
		while(flag){
			memset(cnt,0,sizeof cnt);

			flag=0;
			int now = s[0]=='O'?1:0;
			string ss = "";
			for(int i=1;i<s.length();i++){
				if(now==1&&s[i]=='O'){
					flag=1;
					cnt[i-1]=cnt[i]=-1;
					break;
				}
				else if(now==-1){
					now = s[i]=='O'?1:0;
				}else if(now==1&&s[i]=='o'){
					now =0;
				}else if(now==0&&s[i]=='O'){
					now = 1;
				}else if(now==0&&s[i]=='o'){
					cnt[i-1]=1;
					cnt[i]=-1;
					flag=1;
					break;
				}
			}
			for(int i=0;i<s.length();i++){
				if(cnt[i]==1) ss+='O';
				if(cnt[i]==0) ss+=s[i];
			}
			s=ss;
		}
		cout<<s<<endl;
	}

}



TaoTao要吃鸡

时间限制:C/C++ 1秒,其他语言2秒

空间限制:C/C++ 32768K,其他语言65536K
64bit IO Format: %lld

题目描述 


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,还可以再拿第三件物品。

把bug拿的装备的容量变为1.遍历一次所有情况

#include <iostream>
#include <stdio.h>
#include <math.h>
#include <algorithm>
#include <string.h>
using namespace std;
typedef long long  LL;
const LL maxn = 1111;


int dp[222];
int w[222];
int v[222];
int n,m,h;

int f()
{
	memset(dp,0,sizeof dp);
	int vv=h+m;
	for(int i=1;i<=n;i++)
		if(v[i]==0){
			continue;
		}else
		for(int j=vv;j>=w[i];j--){
				dp[j]=max(dp[j],dp[j-w[i]]+v[i]);
		}
	return dp[vv];
}

int main()
{
	while(~scanf("%d",&n)&&n){
		scanf("%d%d",&m,&h);
		int sum = 0;
		for(int i=1;i<=n;i++){
			scanf("%d %d",&w[i],&v[i]);
			if(w[i]==0) sum+=v[i],v[i]=0;
		}
		int ans = 0;
		if(h!=0){
			for(int i=1;i<=n;i++){
				int temp=w[i];
				w[i]=1;
				ans=max(ans,f());
				w[i]=temp;
			}
			printf("%d\n",ans+sum);

		}else{
			printf("%d\n",f()+sum);
		}
	}



}



C题:

链接:https://www.nowcoder.com/acm/contest/74/C
来源:牛客网

小仙女过生日啦,好多名人都来了,像是小金刚,凹凸曼,光头强啊。来了那么多人,小仙女羞涩的躲了起来。这时,空气中传来了一缕蛋糕的香气,小仙女再也顾不得羞涩了,冲了出来两眼冒绿光的看着(n边形)蛋糕,小仙女心想:emmmm。。。人好多啊,自己一个人吃不好啊。可是我想吃大份啊!!!怎么办怎么办!!!小G看到了这一幕,为了让小仙女不能开开心心的吃大的蛋糕,只能是沿着对角线切切(n-3)次,切成三角形,切成(n-2)块把最大的那一块给小仙女,现在想怎么才能让最大的那块蛋糕最小呢。



题解


要注意的是这题min一定要设置为0x3f3f3f3f.不知道为什么。反之这次训练赛总有莫名其妙的wa点。体验极差。


#include <string>
#include <string.h>
#include <iostream>
#include <vector>
#include <math.h>
#include <stdio.h>
using namespace std;
const int maxn = 200;
struct point
{
	double x,y;
}p[maxn];
double dp[maxn][maxn];
int n;
double dis(int i,int j)
{
	double x = p[i].x-p[j].x;
	double y = p[i].y-p[j].y;
	return sqrt(x*x+y*y);
}
double mul(int a,int b,int c)
{
	double x = dis(a,b),y=dis(b,c),z=dis(a,c);
	double p = x+y+z;
	p/=2;
	return sqrt(p*(p-x)*(p-y)*(p-z));
}
bool check(int a,int b,int c)
{
	double pre = mul(a,b,c);
	for(int i=1;i<=n;i++){
		if(i==a||i==b||i==c) continue;
		double now = mul(a,b,i)+mul(a,c,i)+mul(b,c,i);
		if(fabs(now-pre)<1e-8) return false;
	}
	return true;
}

double dfs(int l,int r)
{
	if(dp[l][r]>-1) return dp[l][r];
	if(r-l<2) return 0;
	if(r-l==2){
		return mul(l,l+1,r);
	}else{
		double Min = 0x3f3f3f3f;//一定要是这个,不然wa到死。
		for(int i=l+1;i<r;i++){
			if(check(l,i,r)){
				double Max = max(mul(l, i, r), max(dfs(i,r),dfs(l,i)));
				Min = min(Min,Max);
			}
		}
		return dp[l][r]=Min;
	}
}

int main()
{
	while(~scanf("%d",&n)){
		for(int i=1;i<=n;i++){
			scanf("%lf%lf",&p[i].x,&p[i].y);

		}
		memset(dp,-1,sizeof dp);
		printf("%.1lf\n",dfs(1,n));
	}

	return 0;
}




YB要打炉石

时间限制:C/C++ 1秒,其他语言2秒

空间限制:C/C++ 32768K,其他语言65536K
64bit IO Format: %lld

题目描述 

Wozuinb非常喜欢打炉石传说,但是菜的不行,所以他决定打
竞技场来练练手。系统按顺序给出n张卡牌,每张卡牌都有自
己的使用消耗a[i],每次只给出一张,wozuinb可以选择或者
弃掉这张牌。每选择一张牌都会按选择顺序放在卡槽中,当
卡槽中放满30张即可组成一套套牌。Wozuinb希望自己的套牌的
消耗满足一个平滑的曲线,即30张卡牌都满足第i张卡牌的消耗
不小于第i-1张(i>1)。请你帮助wozuinb看一看,这些卡牌能不
能组成想要的套牌,如果能组成输出“yes”,如果不能输出“no”。

输入描述:

第一行输入一个整数n,0<n<100。
第二行输入一行数字a[i],每个数字用空格隔开,代表第i张出现的卡牌的消耗。

输出描述:

输出一行,“yes”或“no”
示例1

输入

5
1 2 3 4 5

输出

no

不绝对的最长上升子序列。

while输入wa。


#include <iostream>
#include <stdio.h>
#include <math.h>
#include <algorithm>
#include <string.h>
using namespace std;
typedef long long  LL;
const LL maxn = 1111;
LL a[maxn];
LL cnt[maxn];
int main()
{
	LL n ;
	scanf("%lld",&n);
		for(LL i=1;i<=n;i++)
			scanf("%lld",&a[i]);
		memset(cnt,0,sizeof cnt);
		cnt[1]=a[1];
		LL len = 1;
		for(LL i=2;i<=n;i++){
			if(a[i]>=cnt[len]){
				cnt[++len]=a[i];
			}else{
				LL temp = upper_bound(cnt+1,cnt+1+len,a[i])-cnt;
				cnt[temp]=a[i];
			}
		}
//		printf("%lld\n",len);
		if(len>=30){
			printf("yes\n");
		}else{
			printf("no\n");
		}


}




小G有一个大树

时间限制:C/C++ 1秒,其他语言2秒

空间限制:C/C++ 32768K,其他语言65536K
64bit IO Format: %lld

题目描述 

小G想要把自己家院子里的橘子树搬到家门口(QAQ。。就当小G是大力水手吧)
可是小G是个平衡性灰常灰常差的人,他想找到一个这个橘子树的平衡点。
怎么描述这棵树呢。。。就把它看成由一个个节点构成的树吧。结点数就
代表树重。

输入描述:

多组数据输入输出,
第一行包含一个整数n(3<=n<=1000)代表树的结点的个数
以下n-1行描述(1-n)节点间的连接关系。

输出描述:

输出两个个整数 x,num 分别代表树的平衡点,和删除平衡点后最大子树的结点数(如果结点数相同输出编号小的)。
示例1

输入

3
1 2
1 3

输出

1 1

根本看不懂题目。



#include <string>
#include <string.h>
#include <iostream>
#include <vector>
#include <math.h>
#include <stdio.h>
using namespace std;
const int mod = 100000000;
const int maxn = 1<<14;
vector<int>G[maxn];
int num[maxn];
int ansx,ansnum;
int n;
//
//树的平衡点? 我没学过
void dfs(int u,int pre)
{
	num[u]=1;
	int m=0;
	for(int i=0;i<G[u].size();i++){
		int to = G[u][i];
		if(to==pre) continue;
		dfs(to,u);
		num[u]+=num[to];
		m=max(m,num[to]);
	}
	m=max(m,n-num[u]);
	if(m<ansnum){
		ansnum=m;
		ansx=u;
	}else if(m==ansnum){
		ansx=min(ansx,u);
	}

}

int main()
{
	while(~scanf("%d",&n)){
		ansnum=0x3f3f3f3f;
		for(int i=1;i<=n;i++) G[i].clear(),num[i]=0;
		for(int i=1;i<n;i++){
			int l,r;scanf("%d %d",&l,&r);
			G[l].push_back(r);
			G[r].push_back(l);
		}
		dfs(1,0);
		printf("%d %d\n",ansx,ansnum);
	}

	return 0;
}






德玛西亚万岁

时间限制:C/C++ 1秒,其他语言2秒

空间限制:C/C++ 32768K,其他语言65536K
64bit IO Format: %lld

题目描述 

德玛西亚是一个实力雄厚、奉公守法的国家,有着功勋卓著的光荣军史。
这里非常重视正义、荣耀、职责的意识形态,这里的人民为此感到强烈自豪。
有一天他们想去制裁邪恶的比尔吉沃特,于是派遣了自己最优秀的战士。
结果比尔吉沃特领土太小,只有长为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入门题


#include <string>
#include <string.h>
#include <iostream>
#include <queue>
#include <math.h>
#include <stdio.h>
using namespace std;
const int mod = 100000000;
int kind[5000];
int dp[5000][20];
int mp[22];
int n,m;
int num=0;
void dfs()
{
	for(int i=0;i<=((1<<m)-1);i++){
		if((i&(i<<1))==0){
			kind[++num]=i;
		}
	}
}


int main()
{
	while(~scanf("%d %d",&n,&m)){
        memset(mp,0,sizeof mp);
		for(int i=1;i<=n;i++){
			for(int j=1,x;j<=m;j++){
				scanf("%d",&x);
				if(x==0) mp[i]+=1<<(j-1);
			}
		}
		memset(dp,0,sizeof dp);
        
		num=0;
		dfs();
		for(int j=1;j<=num;j++){
			int x=kind[j];
			if((x&mp[1])==0){
				dp[j][1]=1;
			}
		}
		for(int i=2;i<=n;i++){
			for(int j=1;j<=num;j++){
				int x=kind[j];
				for(int k=1;k<=num;k++){
					int y=kind[k];
					if((x&y)>0) continue;
					if((y&mp[i])>0) continue;
					(dp[k][i]+=dp[j][i-1])%=mod;
				}
			}
		}
		int ans=0;
		for(int i=1;i<=num;i++){
			(ans+=dp[i][n])%=mod;
		}
		printf("%d\n",ans);
	}
	return 0;
}





送分了QAQ

时间限制:C/C++ 1秒,其他语言2秒

空间限制:C/C++ 32768K,其他语言65536K
64bit IO Format: %lld

题目描述 

杭州人称傻乎乎的人为62,而嘟嘟家这里没有这样的习俗。
相比62,他那里的人更加讨厌数字38,当然啦,还有4这个
数字!所以啊,嘟嘟不点都不想见到包含38或者4的数字。
每次给出一个区间[n,m],你能找到所有令人讨厌的数字吗?

输入描述:

多组输入输出;
输入的都是整数对n、m(0<n≤m<1000000),
如果遇到都是0的整数对,则输入结束。

输出描述:

对于每次的输入
输出全部令人讨厌的数的个数
示例1

输入

1 100
0 0

输出

20

数位DP。


#include <iostream>
#include <stdio.h>
#include <math.h>
#include <algorithm>
#include <string.h>
using namespace std;
typedef long long  LL;
const int maxn = 111;
int num[11];
int dp[11][3][11];

int dfs(int pos,int sta,bool limit,int pre)
{
	if(pos==0&&(sta==1||sta==2)) return 1;
	if(pos==0) return 0;
	if(pre!=-1&&!limit&&dp[pos][sta][pre]!=-1) return dp[pos][sta][pre];
	int up=limit?num[pos]:9;
	int temp=0;
	for(int i=0;i<=up;i++){
		if(pre==3&&i==8){
			temp+=dfs(pos-1,1,limit&&i==num[pos],i);
		}else if(i==4){
			temp+=dfs(pos-1,1,limit&&i==num[pos],i);
		}else{
			temp+=dfs(pos-1,sta,limit&&i==num[pos],i);
		}
	}
	if(!limit&&pre!=-1) dp[pos][sta][pre]=temp;
	return temp;
}


int f(int x)
{
	int cnt=0;
	while(x){
		num[++cnt]=x%10;
		x=x/10;
	}
	return dfs(cnt,0,true,-1);
}
int main()
{
	int n,m;
	memset(dp,-1,sizeof dp);
	while(scanf("%d %d",&n,&m)){
		if(n+m==0) break;
		printf("%d\n",f(m)-f(n-1));
	}
}


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值