新生周赛小结


搜索加大数的周赛,结果不是很让人满意啊~我这队长水平一般,只能提供环境希望他们多努力努力了~

把几道不算水的题拿出来解析一下~

A  Zipper

一道算搜索的递归题,题目大意是,给三个字符串,问第三个是否是前两个字符串嵌套成的.题目叫拉链~基本就那意思了.

基本思想就是递归对比,有几个要注意的地方:

1. 要从后往前比,

2. 当a[i]==b[j]时要挨个试.

源代码:

#include <myhead>
const int N=500;
char a[N],b[N],c[N];

int dfs(int x,int y,int z) {
	if(z<0) {
		return true;
	}
	if(x>=0&&a[x]==c[z]) {
		if(dfs(x-1,y,z-1))
			return true;
	}
	if(y>=0&&b[y]==c[z]) {
		if(dfs(x,y-1,z-1))
			return true;
	}
	return false;
}

int main() {
	int t,m=1;
	scanf("%d",&t);
	while(t--) {
		scanf("%s%s%s",a,b,c);
		if(dfs(strlen(a)-1,strlen(b)-1,strlen(c)-1)) {
			printf("Data set %d: yes\n",m);
		} else {
			printf("Data set %d: no\n",m);
		}
		m=m+1;

	}
	return 0;
}

还有一种做法是动态规划:

状态数组为 bool dp[i][j] , 也就是c[i+j]由a的前i个和b的前j个组成.

状态转移方程为:

dp[0][0] = 1;

dp[i][0]=dp[i-1][0]&&a[i-1]==c[i-1];       i>0

dp[0][j]=dp[0][j-1]&&b[j-1]==c[j-1];       j>0

dp[i][j] = (dp[i-1][j]&&a[i]==c[i+j]) || (dp[i][j-1]&&b[j]==c[i+j]);    i,j>0

源代码:

#include <myhead.h>

const int N=210;

int main()
{
	int t,m=1;
	bool dp[N][N];
	string a,b,c;
	cin>>t;
	while(t--) {
		memset(dp,0,sizeof(dp));
		cin>>a>>b>>c;
		dp[0][0]=1;
		for(size_t i=1;i<=a.size();++i) {
			dp[i][0]=(dp[i-1][0]&&a[i-1]==c[i-1]);
		}
		for(size_t j=1;j<=b.size();++j) {
			dp[0][j]=(dp[0][j-1]&&b[j-1]==c[j-1]);
		}
		for(size_t i=1;i<=a.size();++i) {
			for(size_t j=1;j<=b.size();++j) {
				dp[i][j]=(dp[i-1][j]&&a[i-1]==c[i+j-1]) || (dp[i][j-1]&&b[j-1]==c[i+j-1]);
			}
		}
		if(dp[a.size()][b.size()]) {
			printf("Data set %d: yes\n",m);
		} else {
			printf("Data set %d: no\n",m);
		}
		m=m+1;
	}
	return 0;
}


B  Flip Game

http://blog.csdn.net/gj_fb_dabai/article/details/8742470

直接发链接了~


E  Square

http://poj.grids.cn/practice/1011/ 差不多~

题目大意:

给n个数 ,问这n个数能不能组成一个正方形.

解题思想:

一道普通的回溯法dfs, 状态组为(剩余长度num,已经分了几堆m,总共的剩余长度ssum,当前搜到的位置s);初始状态为 (sum/4,1,sum,0).

直接搜索当然会超时,需要有几点注意.

 1.当m==3时即可退出,因为若所有数的合sum%4==0 最后剩余的一组一定满足条件.

 2.对数组按从大到小顺序排序,这样只要搜索比当前值大的值即可.

状态转移方程为:

num<0 -> return false;
num==0
   ->  m==3 -> return true;
   ->  ssum%(4-m)==0 -> return (sum/4,m+1,ssum,0);
       else          -> return flase;
num!=0 -> (num-a[i],m,ssum-a[i],i+1);

源代码:

#include <myhead.h>

const int N=30;
int n,sum;
bool _hash[N];
int dis[N];

void init() {
	sum=0;
	memset(_hash,0,sizeof(_hash));
	scanf("%d",&n);
	for(int i=0;i<n;++i) {
		scanf("%d",&dis[i]);
		sum+=dis[i];
	}
	dis[n]=sum;
	sort(dis,dis+n);
}

bool dfs(int num,int m,int ssum,int s) {
	if(num==0) {
		if(m==3) {
			return true;
		} else {
			return dfs(sum/4,m+1,ssum,0);
		}
	}
	for(int i=s;i<n;++i) {
		if(!_hash[i]) {
			_hash[i]=true;
			if(dfs(num-dis[i],m,ssum-dis[i],i+1)) {
				return true;
			}
			_hash[i]=false;
		}
	}
	return false;
}

int main()
{
	int t;
	scanf("%d",&t);
	while(t--) {
		init();
		if(sum%4==0&&dfs(sum/4,1,sum,0)) {
			puts("yes");
		} else {
			puts("no");
		}
	}
	return 0;
}

G:集合加法

知道题本不是值得写的题,但是大一的童鞋们竟然全用双for循环写的,就现写了一个基数排序,然他们脑袋灵活点~

直接源代码了:

#include <myhead.h>

const int N=10010;

int main()
{
    int t;
    scanf("%d",&t);
    while(t--) {
        int s;
        scanf("%d",&s);
        int a_size,b_size,t;
        int a[N],b[N];
        memset(a,0,sizeof(a));
        memset(b,0,sizeof(b));
        scanf("%d",&a_size);
        for(int i=0;i<a_size;++i) {
            scanf("%d",&t);
            a[t]++;
        }
        scanf("%d",&b_size);
        for(int i=0;i<b_size;++i) {
            scanf("%d",&t);
            b[t]++;
        }
        int sum=0;
        for(int i=1;i<s;++i) {
            sum=sum+(a[i]*b[s-i]);
        }
        printf("%d\n",sum);
    }
    return 0;
}

J:HTML

一道模拟题,也没什么意思,全场一看那么长都没写,我就写了~

根据要求 ,<br>换行, <hr>换行输出80个'-', 每80个字符换行一次. 

源代码:

#include <iostream>
#include <string>
using namespace std;

int main()
{
	string szWord;
	int nCount = 0;
	int i;
	while (cin >> szWord)
	{
		if (szWord == "<hr>")
		{
			if (nCount != 0)
				cout << endl;
			for (i=0; i<80; i++)
				cout << "-";
			cout << endl;
			nCount = 0;
		}
		else if (szWord == "<br>")
		{
			cout << endl;
			nCount = 0;
		}
		else
		{
			if (nCount + szWord.size() + (nCount == 0 ? 0 : 1) > 80)
			{
				cout << endl;
				cout << szWord;
				nCount = szWord.size();
			}
			else
			{
				if (nCount != 0)
					cout << " ";
				cout << szWord;
				nCount += szWord.size() + 1;				
			}
		}
	}
	cout << endl;
	return 0;
}




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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值