中南大学第十二届大学生程序设计竞赛网络预选赛 题解

A CSU 2058 跳一跳

这题迷之错误,我给大家写题解,大家要是过了这题可以给我题解不...


B CSU 2055 Well's Lottery

题意:给出一个n,一个x,接下来有n个数,我可以从中选择若干个数进行或运算,如果等于x,我就寻到宝藏,但是老板很坏,他不想让我寻到宝藏,他就把n个数中的某些数改掉,不让我得到x,求老板修改数字个数的最小值。

思路:举个例子:有4个数:15,3,2,5,x=7(就是二进制的111),把所有数换成二进制,15=1111,因为有了一个111没有的1,所有这个数对答案无影响,排除,3=11,2=10,5=101,统计每位1的个数,从右边开始第一个1有两个,第二个1有两个,第三个1有一个,那么答案就是这些数的最小值,就是1。

#include<cstdio>
#include<algorithm>
using namespace std;
int main()
{
	int n;
	int k,t;
	while(~scanf("%d%d",&n,&k))
	{
		int vis[50]={0};
		for(int i=0;i<n;i++)
		{
			scanf("%d",&t);
			if(((t|k)^k)!=0) //如果这个数某一位是1而k的这位是0,排除 
			continue;
			for(int j=0;j<32;j++)
			if((t&(1<<j))!=0) //位运算优先级低,千万记得加括号
			vis[j]++;
		}
		int ans=999999;
		for(int i=0;i<32;i++)
		if((k&(1<<i))!=0)
		ans=min(ans,vis[i]);
		if(ans==999999)
		ans=0;
		printf("%d\n",ans);
	}
}

C CSU 2056 a simple game

这题其实很简单,如果第二个字符串是第一个字符串的子串,那么肯定输出Yes,当然第二个字符串要记得把所有多余的0排除掉,前缀0后缀0都要排除,接下来就是KMP算法字符串匹配了

#include<cstdio>
#include<cstring>
#include<algorithm>
#include<queue>
#include<stack>
#include<map>
#include<vector>
using namespace std;
char s1[1000005],s2[1000005],temp[1000005];

int next1[1000005];
void get()
{
	int i,j,len=strlen(s2);
	next1[0]=-1;
	for(i=0,j=-1;i<len;)
	if(j==-1||s2[i]==s2[j])
	next1[++i]=++j;
	else
	j=next1[j];
}
int kmp()
{
	int i,j,n,len;
	get();
	n=strlen(s1);
	len=strlen(s2);
	for(i=j=0;i<n;)
	{
		if(j==-1||s1[i]==s2[j])
		i++,j++;
		else
		j=next1[j];		
		if(j>=len)
		return 1;
	}
	return 0;	
}
int main()
{
	int T;
	scanf("%d",&T);
	while(T--)
	{
		scanf("%s%s",s1,s2);
		int len1=strlen(s1);
		int len2=strlen(s2);
		if(len2==1&&s2[0]=='0')
		{
			printf("Yes\n");
			continue;
		}
		int p=0;
		while(s2[p]=='0'&&p<len2)//排0 
		p++;
		int p1=len2-1;
		while(s2[p1]=='0'&&p1>=0)
		p1--;
		if(p==len2||p1<0)
		{
			printf("Yes\n");
			continue;
		}
		int tot=0;
		for(int k=p;k<=p1;k++)
		{
			temp[tot++]=s2[k];
		}
		temp[tot]='\0';
		strcpy(s2,temp);
		len2=strlen(s2);
		if(len1<len2) //第二个串长于第一个串,那第二个串肯定不是第一个串的子串 
		{
			printf("No\n");
			continue;
		}
		int flag=kmp();
		if(!flag)//没匹配到,翻转第二个串继续匹配 
		{
			for(int i=0;i<len2;i++)
			{
				temp[len2-i-1]=s2[i];
			}
			temp[len2]='\0';
			strcpy(s2,temp);
			flag=kmp();
		}
		if(flag)
		printf("Yes\n");
		else
		printf("No\n");
	}
}

D CSU 2062 Z's Array

水题直接上代码

#include<cstdio>
#include<cstring>
#include<algorithm>
#include<queue>
#include<stack>
#include<map>
#include<vector>
using namespace std;
int a[1000005];
int main()
{
	int T;
	scanf("%d",&T);
	while(T--)
	{
		int n,i,k,sum=0;
		scanf("%d%d",&n,&k);
		for(i=1;i<=n;i++)
		{
			scanf("%d",&a[i]);
		}
		for(i=2;i<n;i++)
		{
			if(a[i]>a[i-1]&&a[i]>a[i+1])
			sum++;
		}
		if(sum==k)
		printf("Yes\n");
		else
		printf("No\n");
	}

}

E CSU 2059 Water Problem

把Z的边看成无限长,加入第N个Z时,会和前面每一个Z都有9个交点,那么一共增加9*(N-1)个交点,并且会增加9*(N-1)+1个区域,即f[ n ]=f[ n-1 ]+9*(n-1)+1,再推一下变成等差数列求和公式f[ n ]=n+1+9*n*(n-1)/2

#include<cstdio>
#include<cstring>
using namespace std;
int main()
{
	int T;
	scanf("%d",&T);
	while(T--)
	{
		long long n,ans;
		scanf("%lld",&n);
		printf("%lld\n",n+1+n*(n-1)*9/2);
	}
}

F CSU 2061 Z's Coffee

搜索题,这个题就是三个水杯的加强版,三个水杯的原型题是三个水杯(南阳oj 21),首先要会三个水杯的解法,然后这个题我加了个f 数组,用来记录这个状态的父亲,我把b水杯目前水量乘以1001+c水杯目前水量表示为 一个状态, 比如12 0 0下一次倒水可能变成7 0 5,那么父亲是 0*1001+0=0,儿子是0*1001+5=5,f[ 5 ]=0,这样就可以在找到最优解的时候顺便把他上层的所有状态表示出来

#include<cstdio>
#include<cstring>
#include<stack> 
#include<algorithm>
using namespace std;
const int maxn=1000+10;
const int inf=9999999;
int vis[maxn][maxn],f[maxn*maxn];
int c1,c2,c3,d,flag,ans;
void init()
{
	for(int i=0;i<maxn;i++)
	memset(vis[i],0,sizeof(vis[i]));
	ans=inf;
}
void dfs(int a,int b,int c,int step,int father)
{
	if(vis[b][c]&&vis[b][c]<=step)
	return;
	vis[b][c]=step;
	f[b*1001+c]=father;
	if(a==d||b==d||c==d)
	{
		if(ans>step)
		flag=b*1001+c;
		ans=min(ans,step);
		return;
	}
	int t=min(c2-b,a);
	if(t)
	dfs(a-t,b+t,c,step+1,b*1001+c);	
	t=min(c3-c,a);
	if(t)
	dfs(a-t,b,c+t,step+1,b*1001+c);
	t=min(c1-a,b);
	if(t)
	dfs(a+t,b-t,c,step+1,b*1001+c);	
	t=min(c3-c,b);
	if(t)
	dfs(a,b-t,c+t,step+1,b*1001+c);	
	t=min(c1-a,c);
	if(t)
	dfs(a+t,b,c-t,step+1,b*1001+c);	
	t=min(c2-b,c);
	if(t)
	dfs(a,b+t,c-t,step+1,b*1001+c); 	
}
void print(int num)
{
	if(num!=-1)
	{	
		print(f[num]);
		int c=num%1001;
		int b=num/1001;
		int a=c1-b-c;
		printf("%d %d %d\n",a,b,c);
		
	}
}
int main()
{
	int T;
	scanf("%d",&T);
	while(T--)
	{
		int a,b,c;
		scanf("%d%d%d%d",&c1,&c2,&c3,&d);
		init();
		dfs(c1,0,0,0,-1);
		if(ans==inf)
		printf("-1\n");
		else
		{
			printf("%d\n",ans);
			f[0]=-1;
			print(flag);
		}
	}
}


猜你喜欢

转载自blog.csdn.net/ccsu_cat/article/details/80571055