17暑期ACM俱乐部个人训练赛第1场 (石油oj) 7.24号



//暑假训练第一场,孤军奋斗,事后各种补题,(ps,说实话,时间点卡的不是很好,12点到17点, 没有午觉,大脑犯困, 各种困,各种累,再者,自己也慢慢的发现 精力开始不放在算法上了, 很多时候在做其他事, 别人在群里,或者是在哪里讨论题目的时候,不知何时,自己开始不自觉的远离, 开始闭塞门路,有点闭门造车, 所以AC的题目越来越少, 孤军奋斗难免要疼痛万分,)

也罢, 也不知道,我还能在坚持多久, 也许一个月? 也许一年? 也许几天? 8月份对于我来说是一个人生的转折点,如果可以,那么我将暂时放下这一切, 开始一段新的征途,2年后我们再会,但是不呢, 还是这样么?浑浑噩噩.,学的就这么忘了, 做过的就这么过去,到头了,白头如新, 啥也不会, 看起来都会,实则一个也不会, 没有后悔药,只能硬着头皮往前走,

走一步算一步??  真就这么垃圾下去么. 真就荒废了.哎.//






问题 A: 公鸡打鸣

时间限制: 1 Sec   内存限制: 128 MB
提交: 301   解决: 88
[ 提交][ 状态][ 讨论版]

题目描述

鸡国中有两只最喜欢打鸣的公鸡 G1 和 G2,它们每一次打鸣都有一个声音的响度值。
一天清晨,G1 开始先开始打鸣,响度值为 x,G2 听到 G1 的打鸣后也开始打鸣,响度值为 y。G1 和 G2 很想把它们打鸣声音的响度值调成一样。所以它们进行了 k 次协商,每一次协 商后就各自增加或减少一定的响度值再打鸣一次(打鸣的响度值不能小于 0)。G1 和 G2 生 性迟钝,它们不知道其实经过 s(s≤k)次协商后,打鸣声音的响度值已经相同了。 
请编程帮 G1 和 G2 计算一下它们打鸣声音的响度值相同时最少经过了几次协商(即最 小的 s)? 
注意:如果 x 一开始就等于 y,则不需要协商。 

输入

输入共 k+1 行。 
第 1 行三个整数 x,y 和 k,分别表示 G1、G2 第一次打鸣时声音的响度值,共进行了 k次协商并调整打鸣声音的响度值。 
接下来 k 行,每行包含 4 个整数 ai ,xi ,bi ,yi ,表示第 i 次协商 G1 增加(a i 等于 1)或减少(a i 等于-1)的响度值为 xi ,G2 增加(bi 等于 1)或减少(bi 等于-1)的响度值 yi 。 

输出

输出 1 行一个整数,表示至少经过多少次协商后 G1 和 G2 的打鸣响度值已经相同。如果经过 k 次协商后仍然无法相同,则输出“-1”(不包含双引号)。 

样例输入

2 3 3
1 1 -1 0
-1 1 1 1

1 1 -1 1

样例输出

1

提示

在样例 1 中,G1 和 G2 第 1 次打鸣的响度值分别为 2 和 3,不相同。第 1 次协商 G1 增加 1,G2 减少 0,响度值分别为 3 和 3,所以经过 1 次协商后它们两个打鸣的响度值已经相同。经过 3 次协商时,它们的声音也能调成一样,但至少需要 1 次协商就可以了。 


#include <stdio.h>
#include <string.h>

const int N=101000;
int main()
{
	int x,y, k;
		int a[N],b[N],c[N],d[N];
	scanf("%d %d %d",&x,&y,&k);
	{
		memset(a,0,sizeof(a));
		memset(b,0,sizeof(b));
		memset(c,0,sizeof(c));
		memset(d,0,sizeof(d));
		int flag=0;

			
		for(int i=1;i<=k;i++)
		{
			scanf("%d %d %d %d",&a[i],&b[i],&c[i],&d[i]);
		}
		if(x==y)
		{
			flag=1;
			printf("0\n");
		}
		for(int i=1;i<=k;i++)
		{
			x+=a[i]*b[i];
			y+=c[i]*d[i];
			if(x<0)
				x=0;
			if(y<0)
				y=0;
			if(x==y)
			{
				printf("%d\n",i);
				flag=1;
				break;
			}
		}
		if(!flag)
			printf("-1\n");
	}
	return 0;
}


问题 B: 拯救小鸡

时间限制: 1 Sec   内存限制: 128 MB
提交: 82   解决: 40
[ 提交][ 状态][ 讨论版]

题目描述

鸡国最近遇到了一件很棘手的事情,经常有一只老鹰想来抓小鸡。经鸡国情报员探查,这只老鹰打算共来袭击 n 次,第 i 次来的时刻为第 t i  (1≤i≤n)  秒时刻。 
鸡国国王为了保护鸡国中的小鸡,决定派出鸡国警察(鸡国有无穷多个警察)来巡逻。
每个警察巡逻的时间长度都为 t 秒。当老鹰来袭击的时刻至少要有 x 名警察才能抵御老鹰的袭击。另外国王派遣警察有两个原则: 
(1)每个时刻最多只能派遣一名警察。在第 0 秒时刻及第 0 秒之前的时刻(鸡国有负数时刻)也可以事先准备派遣警察,但每个时刻最多也只能派遣一名警察。 
(2)延迟 1 秒执行巡逻任务。第 i 秒时刻派遣的警察,在第 i+1 到 i+t 秒时刻执行巡逻任务。 
为帮助国王节省开支,请帮忙计算至少需要派遣多少名警察才能保证鸡国小鸡不被老鹰抓走? 

输入

输入共 2 行。 
第 1 行输入三个整数 n,t,x,分别表示老鹰总共袭击次数,每个警察巡逻的时间长度为,以及某个时刻能抵挡住老鹰袭击的最少警察数量。 
第 2 行 n 个严格升序排列的正整数 t i  (1≤i≤n),表示第 t i 秒时刻老鹰会发动袭击。 

输出

输出 1 行一个整数,表示总共至少需要派遣多少个警察才能抵御老鹰的 n 次袭击,如果出现无法抵御老鹰的袭击时,输出“-1”(不包含双引号)。 

样例输入

3 3 3

2 3 4

样例输出

5
思路: 枚举时间轴, 找未重复的点

#include <stdio.h>
#include <string.h>
#include <iostream>
#include <queue>
#include <cmath>
#include <algorithm>

using namespace std;

const int N =10000;
typedef long long ll;
/* 思路:
 枚举时间轴, 找需要添加的时间点个数; 
 */ 
ll a[N];
int vis[N];
int main()
{
	int n,t,x;
	ll ans;
	while(cin>>n>>t>>x)
	{
		memset(vis,0,sizeof(vis));
		for(int i=0;i<n;i++)
			cin>>a[i];
		ans=0;
		
		if(t<x)
		{
			cout<<"-1"<<endl;
			continue;
		}
		for(int i=0;i<n;i++)
		{
			for(int j=1;j<=x;j++)
			{
				int temp=a[i]-t+j;
				
				if(!vis[temp])
				{
					vis[temp]=1;
					ans++;
				}
			}
		}
		
		cout<<ans<<endl;
	}
	return 0;
}


问题 C: 母鸡下蛋

时间限制: 1 Sec   内存限制: 128 MB
提交: 261   解决: 61
[ 提交][ 状态][ 讨论版]

题目描述

鸡国中的母鸡最擅长下蛋了,MGMG 是鸡国中一只以下蛋产量高而闻名全鸡国的母鸡。 
鸡国专供下蛋的 n 个鸡窝呈一字排列在鸡国的“下蛋中心”,从左到右依次编号为 1 到n。每个鸡窝都有一个最大可下蛋的量,其中第 i 个鸡窝的最大可下蛋量为 ci 。有时候由于MGMG 产量实在太大而无法在一个鸡窝中下完所有的蛋,不得不转移到隔壁的鸡窝继续下蛋,如果隔壁的鸡窝还是不能让它下完所有的蛋,则 MGMG 继续转移,直到下完所有的蛋,或者向“下蛋中心”管理员投诉“鸡窝数量实在太少了,我一只鸡的下蛋量都装不下!”。 
为了节省转移时所耗费的体力,请你编程帮助 MGMG 找若干个连续的鸡窝(个数尽量少),让它能下完所有的蛋。 

输入

输入共 2 行。 
第 1 行输入两个整数 n 和 t,表示“下蛋中心”有 n 个可供下蛋的鸡窝,MGMG 一次总共要下 t 个鸡蛋。 
第 2 行 n 个正整数 ci (1≤i≤n),依次表示第 i 个鸡窝最大可下蛋量为 ci 个。 

输出

输出 1 行一个整数或一个单词。当输出整数时表示让 MGMG 下完所有的蛋至少需要几个连续的鸡窝。当 MGMG 用完所有的鸡窝都无法下完所有的蛋时,MGMG 表示非常愤怒,输出单词“Angry”(不包含双引号,注意大小写)。 

样例输入

5 4

1 2 1 2 3

样例输出

2

思路,dp 类似最长子序列


#include <stdio.h>
#include <string.h>
#include <iostream>
#include <queue>
#include <cmath>
#include <algorithm>

using namespace std;

typedef long long ll;


const int N =101000;
ll dp[N];

int main()
{
	int n,t;
	while(cin>>n>>t)
	{
		int x;
		memset(dp,0,sizeof(dp));
		for(int i=1;i<=n;i++)
		{
			cin>>x;	
			dp[i]=dp[i-1]+x;
		}	
		if(dp[n]<t)
		{
			cout<<"Angry"<<endl;
			continue;
		}
		 ll ans=N;
		 ll le=0,ri=n;
		for(int i=1;i<=n;i++)
		{
			
			while(dp[i]-dp[le]>=t&&i>le)
			{
				if(i-le<ans)
				{
					ans=i-le;
				}
				le++;
			}
			
		}
		cout<<ans<<endl;
	}
	
	return 0;
}


问题 D: 鸡国福利

时间限制: 1 Sec   内存限制: 128 MB
提交: 132   解决: 10
[ 提交][ 状态][ 讨论版]

题目描述

鸡国为了表彰鸡国每一只鸡在过去一年的优秀表现,打算在接下来的 n 天中每天给鸡国的一只鸡发 1 袋或者 2 袋“鸡币”(鸡国的通用货币)作为福利。国王要求每天来领钱鸡
互不相同,即来领过钱的鸡不能再来,否则将受到严厉的处罚。 
但聪明的鸡国老百姓侦察后发现国王每天发的钱袋子里面装的钱数量是不一样的(同一天的相同),第 i 天发的每一袋钱为 a i 元。如果第 i 天来领钱的鸡领 1 袋钱,它可以获得ai 元的“鸡币”,如果它领 2 袋钱,则可以获得 2×ai 元“鸡币”,当然它也可以放弃,则第i 天的钱国王收回国库。 
由于鸡国生活条件优越和鸡的贪念等原因,当第 i 天领钱的鸡同时满足以下两个条件时它才会感到幸福: 
(1)领到的钱不能低于鸡国的平均收入 m 元。 
(2)要跟它前面领了钱且感到幸福的鸡一样幸福或者更幸福。 
仁慈的国王希望鸡国的每一只鸡都能感到幸福,请你帮国王规划一下在这 n 天中怎样给每一只发钱才能让最多的鸡感到幸福? 

输入

输入共 2 行。 
第 1 行输入两个整数 n 和 m,分别表示发钱的天数(或理解为来领钱的鸡数)和鸡国的平均收入。 
第 2 行 n 个正整数 ai  (1≤i≤n),依次表示第 i 天发的一袋钱中的“鸡币”为 ai 元。。 

输出

输出 1 行一个整数,表示最多可以让多少只鸡感到幸福。 

样例输入

2 1

2 1

样例输出

2


ing....



问题 E: chicken

时间限制: 1 Sec   内存限制: 128 MB
提交: 134   解决: 92
[ 提交][ 状态][ 讨论版]

题目描述

小 x 非常喜欢小鸡翅。他得知 NSC 超市为了吸引顾客,举行了如下的活动:
一旦有顾客在其他超市找到更便宜的小鸡翅,NSC 超市将免费送给顾客 1000g 小 鸡翅。小 x 为了尽可能的省钱,走遍了各大超市,统计了小鸡翅的价格。NSC 的 工作人员通过不法手段盗取了这些资料。现在 NSC 的工作人员希望你能帮他们 定一个尽可能低的价格(1000g 小鸡翅的价格),使小 x 吃不到免费的小鸡翅。

输入

第一行两个正整数 XNSC (1 ≤ XNSC ≤ 100) 和 YNSC (1 ≤ YNSC ≤ 1000),表示现在在 NSC 超市,YNSCg 小鸡翅要卖 XNSC 元。
第二行一个正整数 N,表示其他超市的个数。
接下来 N 行,每行两个正整数 Xi(1 ≤ Xi ≤ 100) 和 Yi(1 ≤ Yi ≤ 1000), 表示在第 i 家超市,Yig 小鸡翅卖 Xi 元。

输出

有且仅有一行,包含一个实数 A,表示 NSC 超市可以定的最高价格:A 元/ 千克。A 保留两位小数。

样例输入

5 100

3

4 100

3 100

7 100

样例输出

30.00


#include <stdio.h>


int main()
{
	int x,y,n;
	scanf("%d %d",&x,&y);
	scanf("%d",&n);
	double a[10000],b[1000],c[1000];
	double ans=10000;
	double res=0;
	for(int i=0;i<n;i++)
	{
		scanf("%lf %lf",&a[i],&b[i]);
		c[i]=a[i]/b[i];
		if(c[i]<ans)
		{
			ans=c[i];
		}	
	}
	printf("%.2f\n",ans*1000);
	return 0;
}


问题 F: match

时间限制: 1 Sec   内存限制: 128 MB
提交: 76   解决: 30
[ 提交][ 状态][ 讨论版]

题目描述

小 x 在解说 F7 决赛时的搭档是韩乔生,以至于小 x 没有任何能说上话的机会。无聊的他玩起了填字游戏。一个 3*3 的九宫格里,每个格子里都被填上了一个字母,从而我们得到了 6 个单词。现在,小 x 随手写了 6 个单词,他想让你帮他找到一种填字母的方案,使得这 6 个单词都出现在了九宫格里。

输入

共六行,每行一个长度为 3 的单词(全部大写)。

输出

如果找不到方案,输出“0”(不包含引号)
如果能找到,输出包含 3 行,第 i 行对应九宫格的第 i 行(最后一行行末要换行)。
如果有多种方案,请输出每种方案对应的字符串中字典序最前的一种(将行与行首尾相连,就可以得到一个字符串)。

样例输入

ANA

ANA

DAR

DAR

RAD
RAD

样例输出

DAR

ANA

RAD



#include <stdio.h>
#include <string.h>
#include <queue>
#include <iostream>
#include <cmath>
#include <cstring>

using namespace std;

string str[6];
void sorts()
{
	for(int i=0;i<6;i++)
	{
		
		for(int j=0;j<5-i;j++)
		{	
			string temp;
			if(str[j]>str[j+1])
			{
				temp=str[j];
				str[j]=str[j+1];
				str[j+1]=temp;
			}
		}
	}
}
bool judge(int x,int y,int z)
{
	for(int i=0;i<6;i++)
	{
		int flag=1;
		if(i!=x&&i!=y&&i!=z)
		{
			for(int j=0;j<3&&flag;j++)
			{
				if(str[i][0]==str[x][j]&&str[i][1]==str[y][j]&&str[i][2]==str[z][j])
					flag=0;	
					
			}
			if(flag)
				return false;
		}
			
	}
	
	return true;
}
int main()
{
	for(int i=0;i<6;i++)
	{
		cin>>str[i];
	}
	sorts();
	int flag=0;
	for(int i=0;i<6&&!flag;i++)
		for(int j=0;j<6&&!flag;j++)
			for(int k=0;k<6&&!flag;k++)
			{
				if(i!=j&&i!=k&&j!=k)
				{
					if(judge(i,j,k))
					{
						cout<<str[i]<<endl;
						cout<<str[j]<<endl;
						cout<<str[k]<<endl;
						flag=1;
					}
				}
			}
			
	if(!flag)
		printf("0\n");
	return 0;
}



问题 G: 【动态规划】cirs

时间限制: 1 Sec   内存限制: 128 MB
提交: 128   解决: 49
[ 提交][ 状态][ 讨论版]

题目描述

Czyzoiers 都想知道小 x 为什么对鸡蛋饼情有独钟。经过一番逼问,小 x 道出了实情:因为他喜欢圆。最近小 x 又发现了一个关于圆的有趣的问题:在圆上有2N 个不同的点,小 x 想用 N 条线段把这些点连接起来(每个点只能连一条线段),使所有的线段都不想交,他想知道这样的连接方案有多少种?

输入

有且仅有一个正整数 N(N≤3000)。

输出

要求的方案数(结果 mod 100000007)。

样例输入

2

样例输出

2

提示

1 号点与 2 号点连接:2 种。
1 号点与 4 号点连接:1 种。
1 号点与 6 号点连接:2 种。


这种题: 2 5 14 基本上可以确定为卡特兰数

卡特兰数的几种求法

数组表示                       数组表示c[i]=c[i-1]*(4*i-2)/(i+1); //不能超过大数模板

dp[1][1]=1; //可到40

for(i=2;i<40;i++)

for(j=1;j<=i;j++)

{

dp[i][j]=dp[i-1][j]+dp[i][j-1];

}

dp[i][i]==//卡特兰数

 

a[0]=1;

a[1]=1;

a[2]=2;        

for(inti=3;i<=n;i++)

{

for(int j=1;j<=i;j++)

a[i]=(a[i]+a[i-j]*a[j-1])%MOD;

}


#include <stdio.h>
#include <iostream>
#include <string.h>
using namespace std;

typedef long long ll;
/*
卡特兰数
*/ 
const int N=101000;
const int MOD=100000007;
ll a[N];
int main()
{

	int n;
	while(~scanf("%d",&n))
	{
		memset(a,0,sizeof(a));
		a[0]=1;
		a[1]=1;
		a[2]=2;	
		for(int i=3;i<=n;i++)
		{
			for(int j=1;j<=i;j++)
				a[i]=(a[i]+a[i-j]*a[j-1])%MOD;
		}
		printf("%lld\n",a[n]);
	}
	return 0;
}


问题 H: wtaxi

时间限制: 1 Sec   内存限制: 128 MB
提交: 65   解决: 32
[ 提交][ 状态][ 讨论版]

题目描述

话说小 x 有一次去参加比赛,虽然学校离比赛地点不太远,但小 x 还是想坐出租车去。大学城的出租车总是比较另类,有“拼车”一说,也就是说,你一个人坐车去,还是一堆人一起,总共需要支付的钱是一样的(每辆出租上除司机外最多坐下 4 个人)。刚好那天同校的一群 Oier 在校门口扎堆了,大家果断决定拼车去赛场。
问题来了,一辆又一辆的出租车经过,但里面要么坐满了乘客,要么只剩下一两个座位,众 Oier 都觉得坐上去太亏了,小 x 也是这么想的。
假设 N 位 Oier 准备拼车,此时为 0 时刻,从校门到目的地需要支付给出租车师傅 D 元(按车次算,不管里面坐了多少 Oier),假如 S 分钟后恰能赶上比赛,那么 S 分钟后经过校门口的出租车自然可以忽略不计了。现在给出在这 S 分钟当中经过校门的所有的 K 辆出租车先后到达校门口的时间 Ti 及里面剩余的座位 Zi(1 <= Zi <= 4),Oier 可以选择上车几个人(不能超过),当然,也可以选择上 0 个人,那就是不坐这辆车。
俗话说,时间就是金钱,这里小 x 把每个 Oier 在校门等待出租车的分钟数等同于花了相同多的钱(例如小 x 等待了 20 分钟,那相当于他额外花了 20 元钱)。
在保证所有 Oier 都能在比赛开始前到达比赛地点的情况下,聪明的你能计算出他们最少需要花多少元钱么?

输入

每组数据以四个整数 N , K , D , S 开始,具体含义参见题目描述。
接着 K 行,表示第 i 辆出租车在第 Ti 分钟到达校门,其空余的座位数为 Zi(时间按照先后顺序)。
N <= 100,K <= 100,D <= 100,S <= 100,1 <= Zi <= 4,1<= T(i) <= T(i+1) <= S

输出

对于每组测试数据,输出占一行,如果他们所有人能在比赛前到达比赛地点,
则输出一个整数,代表他们最少需要花的钱(单位:元),否则请输出“impossible”。

样例输入

2 2 10 5

1 1

2 2

样例输出

14


dp, 

#include <stdio.h>
#include <string.h>
#include <cstring>
#include <iostream>
#include <cmath>
#include <algorithm>
const int inf= 1<<29;
using namespace std;

void init(int *p)
{
	for(int i=0;i<250;i++)
		p[i]=inf;
}

int dp[250],pre[250];
int main()
{
	init(dp);
	init(pre);
	int n,k,d,s;
	while(cin>>n>>k>>d>>s)
	{
		dp[0]=0;
		int t,z;
		while(k--)
		{
			cin>>t>>z;
			memcpy(pre,dp,sizeof(dp));	
			for(int i=0;i<=n;i++)// 人 
			{
				for(int j=0;j<=z;j++)// 车 
				{
					dp[i]=min(dp[i],pre[i-j]+d+j*t);	
				}
			}
		}
		if(dp[n]!=inf)
			printf("%d\n",dp[n]);
		else
			printf("impossible\n");
	}
	return 0;
}


问题 I: 【分治】化装晚会

时间限制: 1 Sec   内存限制: 64 MB
提交: 175   解决: 76
[ 提交][ 状态][ 讨论版]

题目描述

万圣节又到了!FJ打算带他的奶牛去参加化装晚会,但是,FJ只做了一套能容下两头总长不超过S (1≤S≤1000000)的奶牛恐怖服装。FJ养了N(2≤N≤20000)头按1--N顺序编号的奶牛,编号为i的奶牛的长度为L_i(1≤L_i≤1000000)。如果两头奶牛的总长度不超过S,那么她们就能穿下这套服装。
FJ想知道,如果他想选择两头不同的奶牛来穿这套衣服,一共有多少种满足条件的方案。

输入

第1行是2个整数:N和S;
第2~N+l行每行一个整数:L_i。

输出

1个整数,表示FJ可选择的所有方案数。注意奶牛顺序不同的两种方案是被视为相同的。

样例输入

4 6
3
5

2

1

样例输出

4

提示

样例说明:4种选择分别为:奶牛1和奶牛3;奶牛l和奶牛4;奶牛2和奶牛4;奶牛3和奶牛4。


先排序,然后二分查找, 

#include<cstdio>
#include<algorithm>
using namespace std;
typedef long long ll;
 const int inf=1<<29;
ll a[20010],s,n;
ll find(int b,int c)
{
    int l = b,hi = n+1;
	while(l+1 < hi)
	{
		int mid =(l + hi)/2;
		if(a[mid] <= c) 
			l = mid;
		else 
			hi = mid;
	}
   return l-b;
}
int main()
{
	ll i,ans=0; 
	scanf("%d%d",&n,&s);
	for(i=1;i<=n;i++)
	{
		scanf("%d",&a[i]);
	}
	sort(a+1,a+n+1);
	a[0]=-1;
	a[n+1]=inf;
	for(i=1;i<=n;i++)
	{
		ans+=find(i,s-a[i]);
	}
	printf("%lld",ans);
	return 0;
}




问题 J: 【搜索】泡泡龙

时间限制: 1 Sec   内存限制: 64 MB
提交: 160   解决: 65
[ 提交][ 状态][ 讨论版]

题目描述

这是一个简化版的网络游戏:在一个N×N方块构成的棋盘中,每个方块均涂上红、黄、蓝、绿(记为l、2、3、4)中的一种颜色,游戏者可以在最底行任意找一个方块,用鼠标双击这个方块,于是该方块及与之相邻(即在上、下、左、右四个方向上有公共边)的所有的同色方块均被消掉,而因下方失去支持的方块将会自由落下填补空位。样例中给出一个4×4的棋盘样例,当游戏者双击最底层左边第二个方块后,将会形成输出结果的布局。
你的任务是编写一个泡泡龙模拟程序,对于给定的一个初始棋盘,计算游戏者双击最底层某个方块后棋盘的布局将会如何。

输入

第1行有两个正整数N和M(I≤M≤N≤I00),其中N表示棋盘的规模,而M则表示游戏者将双击最底层从左边数起的第M个方块。接下来的N行每行有N个l~4的整数组成,表示一个初始的棋盘,同一行相邻两个数之间用一个空格隔开。

输出

N行,每行用N个数给出游戏结束后棋盘的布局,没有方块的格子用0表示,同一行相邻两个数之间也用一个空格分开。每行末尾有空格

样例输入

4 2

1 2 3 4

4 2 4 4

3 4 4 3

1 4 4 3

样例输出

1 0 0 0 

4 0 0 0 

3 2 0 3 

1 2 3 3 

提示


这道搜索确实确实让我很上头, 我直接四个方向搜索, 我觉着个思路是对的, 但就是过不了;


AC代码:

#include <stdio.h>
#include <string.h>
int maps[100][100];
int dir[4][2]={1,0,-1,0,0,1,0,-1};
int temp,n,m;
void find()
{
	int i,j,k;
	for(i=n;i>=1;i--)
	{
		for(j=1;j<=n;j++)
		{
			if(maps[i][j]==0)
			{
				for(k=i;k>=1;k--)
				{
					if(maps[k][j])
					{
						maps[i][j]=maps[k][j];
						maps[k][j]=0;
						break;
					}
				}
			}
		}
	}
}
void dfs(int x,int y)
{
	for(int i=0;i<4;i++)
	{
		int px=x+dir[i][0];
		int py=y+dir[i][1];
		if(px<1||px>n||py<1||py>n)
			continue;
		if(maps[px][py]==temp)
		{
			maps[px][py]=0;
			dfs(px,py);
		}
	}
}
int main()
{
	while(~scanf("%d %d",&n,&m))
	{
		
		memset(maps,0,sizeof(maps));
		for(int i=1;i<=n;i++)
		{
			for(int j=1;j<=n;j++)
				scanf("%d",&maps[i][j]);
		}
		temp=maps[n][m];
		
		dfs(n,m);
		maps[n][m]=0;
		find();
		for(int i=1;i<=n;i++)
		{
			for(int j=1;j<=n;j++)
			{
				printf("%d ",maps[i][j]);
			}
			printf("\n");
		}	
	}
	return 0;
}


未AC 代码:

#include <stdio.h>
#include <string.h>

int maps[100][100];
int n,m;
int temp;

int find(int x,int y)
{
	int k=0;
	for(int i=x;i>=1;i--)
	{
		if(maps[i][y]!=0)
		{
			k=maps[i][y];
			maps[i][y]=0;
			break;
		}	
	}
	return k;
}
void dfs(int x,int y)
{
	if(maps[x-1][y]==temp)
	{
		maps[x][y]=0;
		dfs(x-1,y);
	}
	if(maps[x][y-1]==temp)
	{
		maps[x][y]=0;
		dfs(x,y-1);
	}
	if(maps[x][y+1]==temp)
	{
		maps[x][y]=0;
		dfs(x,y+1);
	}
	if(maps[x+1][y]==temp)
	{
		maps[x][y]=0;
		dfs(x+1,y);
	}
	maps[x][y]=0;
}
int main()
{ 
	scanf("%d %d",&n,&m);
	for(int i=1;i<=n;i++)
		for(int j=1;j<=n;j++)
			scanf("%d",&maps[i][j]);
	temp=maps[n][m];
	dfs(n,m);
	maps[n][m]=0;
	int k;
	for(int i=n;i>=1;i--)
	{
		for(int j=n;j>=1;j--)
		{
			if(maps[j][i]==0)
			{
				k=find(j-1,i);
				maps[j][i]=k;
			}
		}
	}	
	for(int i=1;i<=n;i++)
	{
		for(int j=1;j<=n;j++)
		{
			printf("%d ",maps[i][j]);
		}
		printf("\n");
	}
	return 0;
}



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

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值