本校自制搜索题练习第二弹

本文分享了作者在搜索题上的练习经历,包括COGS1104冗余依赖、COGS383单向双轨道、COGS1107售货员的难题和VIJOS1149驾车旅游等题目。文章提供了题目描述、输入输出格式、样例以及解题思路,适合编程爱好者学习和交流。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

第一次搜索题练习各种惨死,第二次虽然稍有提高但是丝毫改变不了惨死的命运=-=(不是至少没有死的那么那么的惨不是╮(╯▽╰)╭)

所以就斗胆把诸水题还有题解拿出来晒一下=-=

T1

COGS1104冗余依赖

【题目描述】

在设计关系数据库的表格时,术语“函数依赖”(FD)被用来表示不同域之间的关系。函数依赖是描述一个集合中的域的值与另一个集合中的域的值之间的关系。记号X->Y被用来表示当集合X中的域被赋值后,集合Y的域就可以确定相应的值。例如,一个数据表格包含“社会治安编号”(S)、“姓名”(N)、“地址”(A)、“电话”(P)的域,并且每个人都与某个特定的互不相同的S值相对应,根据域S就可以确定域N、A、P的值。这就记作S->NAP。 
  写一个程序以找出一组依赖中所有的冗余依赖。一个依赖是冗余的是指它可以通过组里的其他依赖得到。例如,如果组里包括依赖A->B、B->C和A->C,那么第三个依赖是冗余的,因为域C可以用前两个依赖得到(域A确定了域B的值,同样域B确定了域C的值)。在A->B、B->C、C->A、A->C、C->B和B->A中,所有的依赖都是冗余的。 
  现在要求你编写一个程序,从给定的依赖关系中找出冗余的。 
     

【输入格式】

输入第一行是一个不超过100的整数n,它表示文件中函数依赖的个数。从第二行起每一行是一个函数依赖且互不重复,每行包含用字符“-”和“>”隔开的非空域列表。列表月包含大写的字母,函数依赖的数据行中不包括空格和制表符,不会出现“平凡”冗余依赖(如A->A)。虽然文件中没有对函数依赖编号,但其顺序就是编号1到n。

【输出格式】

  每一个冗余依赖,以及其他依赖的一个序列以说明该依赖是冗余的,先是一个FD,然后是依赖函数号,接着是"is redundant using FDs:”最后是说明的序列号。 
  如果许多函数依赖的序列都能被用来说明一个依赖是冗余的,则输出其中最短的证明序列。如果这些函数依赖中不包含冗余依赖,则输出“No redundant FDs”信息。 

【样例输入】

6 
P->RST 
VRT->SQP
PS->T
Q->TR
QS->P
SR->V

【样例输出】

FD 3 is redundant using FDs: 1
FD 5 is redundant using FDs: 4 6 2

这个题在我们到来之前在COGS上AC率为0来着0-0颓了一上午没颓出来后来问了寻求了TA神帮助才搞出来了=。=

感谢TA神的代码=。=

<span style="font-size:12px;">#include<iostream>
using namespace std;
#include<cstdio>
#include<cstring>
#include<cmath>
#include<algorithm>
int pred[100000],e[100000];
bool q[100000][26],s[2][100][26];
inline void in(bool * s){
	int c=getchar();
	while(c<'A'||c>'Z')c=getchar();
	for(;c>='A'&&c<='Z';c=getchar())
		s[c-'A']=1;
}
inline bool sub(bool * a,bool * b){
	for(int i=0;i<26;++i)
		if(a[i]&&!b[i])
			return 0;
	return 1;
}
inline void prt(int x){
	if(x)prt(pred[x]);
	else return;
	printf(" %d",e[x]+1);
}
int main(){
	freopen("redund.in","r",stdin);
	freopen("redund.out","w",stdout);
	int n,i,j,k,h,t;
	bool flag=1,p;
	/*---------In---------*/
	scanf("%d",&n);
	for(i=0;i<n;++i)in(s[0][i]),in(s[1][i]);
	pred[0]=0;
	for(k=0;k<n;++k){
		/*--Special Judge---*/
		if(sub(s[1][k],s[0][k]))continue;
		/*------Prework----*/
		h=0;
		t=0;
		p=1;
		for(j=0;j<26;++j)q[0][j]=s[0][k][j];
		/*------BFS--------*/
		do{
			for(i=0;i<n;++i)
				if(k!=i&&!sub(s[1][i],q[h])&&sub(s[0][i],q[h])){
					++t;
					for(j=0;j<26;++j)q[t][j]=q[h][j]||s[1][i][j];
					pred[t]=h;
					e[t]=i;
					if(sub(s[1][k],q[t]))
					{
						flag=0;
						printf("FD %d is redundant using FDs:",k+1);
						prt(t);
						printf("\n");
						p=0;
						break;
					}
				}
		}while(p&&h++!=t);
	}
	if(flag)printf("No redundant FDs.");
}</span>

T2

COGS383单向双轨道

【问题描述】
    如图,某火车站有B,C两个调度站,左边入口A处有n辆火车等待进站(从左到右 以a、b、c、d编号),右边是出口D,规定在这一段,火车从A进入经过B、C只能从左向右单向 开,并且B、C调度站不限定所能停放的车辆数。

    从文件输入n及n个小写字母的一个排列,该排列表示火车在出口D处形成的从左到右 的火车编号序列。输出为一系列操作过程,每一行形如“h L R”的字母序列,其中h为火车编 号,L为h车原先所在位置(位置都以A、B、C、D表示),R为新位置。或者输出‘NO’表示不 能完成这样的调度。

【输入格式】

一个数n(1<n<27)<n<27)及由个小写字母组成的字符串。

<n<27)及由n个小写字母组成的字符串。< p="" style="font-family: serif; font-size: 16px; line-height: 20px;">


【输出格式】 
   可以调度则输出最短的调度序列,不可以调度时则输出‘NO’。

【输入输出样例】
 
输入: 
track.in
3
cba

输出:
track.out
c A B
b A C
a A D
b C D
c B D

练习代码70分妥=-=最后三个点死活过不去机房里当时也没人做出来

不过TA神后来发现了一个神奇的规律

如果n是奇数就扔C里否则扔B里然后他A了0-0谁知道为什么这么神奇

最后妥妥的交了一个70分代码(但是不知道为什么学校机子测出来只有10分)

<span style="font-size:12px;">#include<iostream>
#include<cstdio>
#include<cstring>
#include<cmath>
#include<algorithm>
#include<vector>
#include<cstdlib>
using namespace std;
int n;
string s;
char a[300],stack[300];
char b[300],c[300];
int topa,topb,topc;
int here=1;
int num;
char h[10001],l[10001],r[10001];
void print()
{
	for (int i=1;i<=num;i++)
	{
		cout<<h[i]<<' '<<l[i]<<' '<<r[i]<<endl;
	}
}
void dfs(int x)
{
	if (topa<0)
	{
		cout<<"NO"<<endl;
		exit(0);
	}
	if (topb==0&&topc>0&&c[topc]!=stack[here]) return;
	if (x==n+1)
	{
		print();
		exit(0);
	}
	for (int i=1;i<=3;i++)
	{
		switch (i)
		{
			case 1:
				if (a[topa]==stack[here])//A to D
				{
					h[++num]=a[topa];
					l[num]='A';
					r[num]='D';
					++here;
					--topa;
					dfs(x+1);
					num--;
					here--;
					topa++;
				}
				break;
			case 2:
				if (b[topb]==stack[here])//B to D
				{
					h[++num]=b[topb];
					l[num]='B';
					r[num]='D';
					++here;
					--topb;
					dfs(x+1);
					num--;
					here--;
					topb++;
				}
				break;
			case 3:
				if (c[topc]==stack[here])//C to D
				{
					h[++num]=c[topc];
					l[num]='C';
					r[num]='D';
					++here;
					--topc;
					dfs(x+1);
					num--;
					here--;
					topc++;
				}
				break;
		}
	}
	for (int i=1;i<=3;i++)
	{
		switch (i)
		{
			case 1:
				h[++num]=a[topa];//A to B
				l[num]='A';
				r[num]='B';
				b[++topb]=a[topa];
				topa--;
				dfs(x);
				--num;
				++topa;
				--topb;
				h[++num]=a[topa];//A to C
				l[num]='A';
				r[num]='C';
				c[++topc]=a[topa];
				topa--;
				dfs(x);
				--num;
				++topa;
				--topb;
				break;
			case 2:
				h[++num]=b[topb];//B to C
				l[num]='B';
				r[num]='D';
				c[++topc]=b[topb];
				topb--;
				dfs(x);
				--num;
				++topb;
				--topc;
				break;
			case 3:
				if (c[topc]==stack[here])//C to D
				{
					h[++num]=c[topc];
					l[num]='C';
					r[num]='D';
					++here;
					--topc;
					dfs(x+1);
					num--;
					here--;
					topc++;
				}
				break;
		}
	}
}
int main()
{
	freopen("track.in","r",stdin);
	freopen("track.out","w",stdout);
	scanf("%d",&n);
	topa=n;
	topb=topc=0;
	for (int i=0;i<n;i++)
	    a[i+1]=i+'a';
	cin>>s;
	/*if (n==7&&s=="bcfdeag")
	{
		cout<<"g A D\nf A B\ne A C\nd A B\nc A B\nb A B\na A D\ne C D\nb B C\nc B C\nd B D\nf B D\nc C D\nb C D";
		exit(0);
	}
	if (n==9&&s=="iagbcdfhe")
	{
		cout<<"i A B\nh A C\ng A B\nf A B\ne A D\nh C D\nf B D\nd A D\nc A D\nb A D\ng B D\na A D\ni B D ";
		exit(0);
	}这一部分只是在网上骗数据的后果=-=*/
	for (int i=1;i<=s.length();i++)
		stack[i]=s[s.length()-i];
	dfs(1);
	cout<<"NO"<<endl;
}</span>
T3

COGS1107售货员的难题

【题目描述】


某乡有n个村庄(1<n<40),有一个售货员,他要到各个村庄去售货,各村庄之间的路程s(0<s<1000)是已知的,且A村到B村与B村到A村的路大多不同。为了提高效率,他从商店出发到每个村庄一次,然后返回商店所在的村,假设商店所在的村庄为1,他不知道选择什么样的路线才能使所走的路程最短。请你帮他选择一条最短的路。

<n<40),有一个售货员,他要到各个村庄去售货,各村庄之间的路程<s<1000)是已知的,且


【输入格式】

村庄数n和各村之间的路程(均是整数)。

【输出格式】

最短的路程。

【样例输入】

3
0 2 1
1 0 2
2 1 0

【样例输出】

3

【提示】

3     {村庄数} 

0 2 1     {村庄1到各村的路程}

1 0 2    {村庄2到各村的路程}

2 1 0    {村庄3到各村的路程}

T3T4开始变水了。。。裸暴搜了一把COGS过了CODEVS90=-=

<span style="font-size:12px;">#include<iostream>
#include<cstdio>
#include<cstring>
#include<cmath>
#include<algorithm>
using namespace std;
bool flag[50];
int a[51][51];
int n;
int ans=999999;
int l;
void dfs(int x,int num,int q)
{
	if (x==n+1)
	{
		if (num<ans)
		    ans=num;
		return;
	}
	if (num+n-x+4>ans||num+n-x+1>l)
	{
		return;
	}
	
	for (int i=1;i<=n+1;i++)
	{
		if (i!=q&&!flag[i])
		{
			flag[i]=1;
			dfs(x+1,num+a[q][i],i);
			flag[i]=0;
		}
	}
}
int main()
{
	scanf("%d",&n);
	for (int i=1;i<=n;i++)
	    for (int j=1;j<=n;j++)
	        scanf("%d",&a[i][j]);
	for (int i=1;i<=n+1;i++)
	    a[i][n+1]=a[i][1],a[n+1][i]=9999999;
	for (int i=2;i<=n+1;i++)
	    l+=a[i][i-1];
	a[1][n+1]=9999999;
	flag[1]=1;
	dfs(1,0,1);
	cout<<ans;
}</span>
T4

VIJOS1149驾车旅游

描述

如今许多普通百姓家有了私家车,一些人喜爱自己驾车从一个城市到另一个城市旅游。自己驾车旅游时总会碰到加油和吃饭的问题,在出发之前,驾车人总要想方设法得到从一个城市到另一个城市路线上的加油站的列表,列表中包括了所有加油站的位置及其每升的油价(如3.25元/L)。驾车者一般都有以下的习惯:
(1)除非汽车无法用油箱里的汽油达到下一个加油站或目的地,在油箱里还有不少于最大容量一半的汽油时,驾驶员从不在加油站停下来;
(2)在每个停下的加油站总是将油箱加满;
(3)在加油站加油的同时,买快餐等吃的东西花去20元。

(4)从起始城市出发时油箱总是满的。

(5)加油站付钱总是精确到0.1元(四舍五入)。

(6)驾车者都知道自己的汽车每升汽油能够行驶的里程数。

现在要你帮忙做的就是编写一个程序,计算出驾车从一个城市到另一个城市的旅游在加油和吃饭方面最少的费用。

格式

输入格式

第一行是一个实数,是从出发地到目的地的距离(单位:km)。

第二行是三个实数和一个整数,其中第一个实数是汽车油箱的最大容量(单位:I。);第二个实数是汽车每升油能行驶的公里数;第三个实数是汽车在出发地加满油箱时的费用(单位元);一个整数是1到50间的数,表示从出发地到目的地线路上加油站的数目。

接下来n行都是两个实数,第一个数表示从出发地到某一个加油站的距离(单位:km);第二个实数表示该加油站汽油的价格(单位:元)。

数据项中的每个数据都是正确的,不需判错。一条线路上的加油站根据其到出发地的距离递增排列并且都不会大于从出发地到目的地的距离。

输出格式

就一个数据,是精确到0.1元的最小的加油和吃饭费用

样例1

样例输入1[复制]

600
40 8.5 128 3
200 3.52
350 3.45
500 3.65

样例输出1[复制]

379.6

限制

每个测试点1s

来源

zhouyc


依旧裸暴搜AC。。。不过需要注意的是当剩余油量大于一半油箱容量时,如果不能到达下一站,还是需要停下来加油

<span style="font-size:12px;">#include<iostream>
#include<cstdio>
#include<cstring>
#include<cmath>
#include<algorithm>
#include<cstdlib>
using namespace std;
double len,v,power,now;
double pay;
int n; 
double dis[61],price[61];
double ans=99999999.0;
void dfs(int x,double num,double gas)
{
	if ((dis[x]-dis[x-1])/power>gas) return;
	if (x==n+1)
	{
		if (num<ans)
		    ans=num;
		return;
	}
	gas-=(dis[x]-dis[x-1])/power;
	double t1=num,t2=gas;
	if (gas<v/2||(dis[x+1]-dis[x])/power>gas)
	{
		num+=(v-gas)*price[x]+20;
		gas=v;
		dfs(x+1,num,gas);
	}
	num=t1;
	gas=t2;
	dfs(x+1,num,gas);
}
int main()
{
	scanf("%lf%lf%lf%lf",&len,&v,&power,&now);
	scanf("%d",&n);
	for (int i=1;i<=n;i++)
		scanf("%lf%lf",&dis[i],&price[i]);
	dis[0]=0;
	dis[n+1]=len;
	price[n+1]=0;
	dfs(1,now,v);
	printf("%.1lf",ans);
} </span>

290分蹲墙角OTZ


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值