POJ1110和HDU1298

对于HDU1298主要是要掌握字典树的建立和运用,根据不同的实际情况来调整字典树中存放的数据,然后是搜索方式,主要是利用深搜,但是要注意的是,注意字符的频率。

对于POJ1110主要是在题目的理解以及题目观察能力的运用,对于算法上面,只能说,用不同的数据结构去存放你已经完成过的查询,以减少你的查询次数,有些类似于动态规划的一部分。(虽然这道题最终是WR但是,我觉得题目的要求已经达到了,能过所有测试数据,可能细节还需考究)

上课主要学到了两种算法,一种是对于大数的处理,合理运用数据结构去存放很重要,然后一种是对于一个平面内很多点之间找到两个最短相距的点,首先是把平面分成两半,然后对于每一半去找最短的距离的点,然后对于两半的最短点距求min,然后对于这个最小值还要进行处理,把最前面的分割线两边加上min在,2min距离内的点集求最小距离的点,看有无比min小的,如果有,那才是最优解,这里还可以运用分治的思想,继续不断的划分直到问题能够简单的解决为止,最后再进行整合。

HDU1298

#include<cstdio>
#include<cstdlib>
#include<iostream>
#include<algorithm>
//#include<list>
//#include<stack>
//#include<vector>
//#include<queue> 
//#include<string>
#include<string.h>
#include<cmath> 
//#include<ctype.h>
//#include<set>
//#include<sstream>

using namespace std;
/**
 *1思路:首先将字符串放进树中,在放的同时记得保存字的频率
 *2在查询的时候首先查询第一个节点,每次都要从第一个开始查询
 *3直到查询到最后一个字符的时候才能确定这个字符下对应的最大的频率
 *4当没有这个字符串存在的时候要输出
 *5用二维数组无法完成的理由是,无法存放对应的字符串联系
**/

typedef struct Node
{
	int number;
	char word[120];
	Node *next[26];
	void init()
	{
		number = 0;
		memset(next,NULL,sizeof(next));
	}
}NODE,*PNODE;

PNODE setNode()
{
	PNODE pNew = (PNODE) malloc(sizeof(NODE));
	pNew->init();
	return pNew;
}

PNODE pHead = setNode();/*头结点*/
char numberStr[120];
char resultStr[120];
int maxVAL = 0;
char t9[10][5]={"","","abc","def","ghi","jkl","mno","pqrs","tuv","wxyz"};//手机按键对应字符

void insertNode(char st[120], int number)
{
	char temp[120];
	PNODE pNew = pHead;
	int length = strlen(st);
	int i,j;
	for (i = 0; i < length; i++)
	{
		j = st[i] - 'a';
		if(pNew->next[j] == NULL)
		{
			pNew->next[j] = setNode();
		}
		pNew = pNew->next[j];
		pNew->number += number;
		temp[i] = st[i];/*把每一段到这个节点为止的字符串赋值,并在最后赋值、0否则打印时会出错*/
		temp[i+1] = '\0';
		strcpy(pNew->word , temp);
	}
}

void dfs(PNODE p, int nowPlace, int planPlace)
{
	if(nowPlace == planPlace)
	{
		if(p->number > maxVAL)
		{
			strcpy(resultStr,p->word);
			maxVAL = p->number;
		}
		return;
	}

	int seeNumber = numberStr[nowPlace + 1] - '0';//按下手机哪个按键
	int length = strlen(t9[seeNumber]);//手机按键对应字符长度
	for (int i = 0; i < length; i++)
	{
		if(p->next[t9[seeNumber][i]-'a'] != NULL)
		{
			dfs(p->next[t9[seeNumber][i]-'a'], nowPlace+1, planPlace);
		}
	}
}

int main()
{
	char str[120];
	int s;//外面最大的,一共有几组测试数据
	int resetNumber=1;//轮回次数
	int p=0;//频率temp
	cin>>s;
	while (s--)
	{
		pHead = setNode();
		int w;
		cin>>w;
		while (w--)
		{
			cin>>str;
			cin>>p;
			insertNode(str,p);
		}
		printf("Scenario #%d:\n",resetNumber);
		int m;
		cin>>m;
		while (m--)
		{
			cin>>numberStr;
			int length = strlen(numberStr);
			for (int i = 0; i < length-1; i++)
			{
				maxVAL = -1;
				dfs(pHead, -1, i);//深搜频率最高的
				if(maxVAL == -1)
				{
					cout<<"MANUALLY"<<endl;
				}
				else
				{
					cout<<resultStr<<endl;
				}
			}
			cout<<endl;
		}
		cout<<endl;
		resetNumber++;
	}
	return 0;
}
POJ1110
#include<cstdio>
#include<cstdlib>
#include<iostream>
#include<algorithm>
//#include<list>
//#include<stack>
//#include<vector>
//#include<queue> 
//#include<string>
#include<string.h>
#include<cmath> 
//#include<ctype.h>
//#include<set>
//#include<sstream>

using namespace std;

int map[10][10][10];
int twoWA[10][10][10][10];
int oneAc[10];
char tempStr[120];

/**
 *思路1首先用数组存放所有可能是点的位置
 *2从第一张图开始对比,如果存在有个点的位置是数据量的最大值,则可以用一个点表示
 *3对比时要注意如果存在两张图不能用同样的两个点区分且没有更多的可能性输出
 *4从上到下,从左到右
**/

int checkAllMapIsAC(int n,int r,int c,int r2,int c2)
{
	int repate = 0;
	for (int i = 0; i < n; i++)
	{
		if((map[i][r][c] != 1) && (map[i][r2][c2] != 1))
			repate++;
		if(repate >=2 )
			return 2;
	}
	return repate;
}

int checkAllMapIsOneAC(int n,int r,int c)//如果只有一个o那么这个点是被允许的
{
	int repate = 0;
	int n1;
	for (int i = 0; i < n; i++)
	{
		if(map[i][r][c] == 2)
		{
			repate++;
			n1 = i;
		}
	}
	if(repate == 1)
	{
		if(oneAc[n1] != -1)
		{
			map[n1][r][c] = 3;//一个点已经被ac了
			oneAc[n1] = -1;//记录是哪个map已经有了#
		}
		return n1;
	}
	else
	{
		return -1;
	}
}

int checkAllMapIsTwoAC(int nowN, int nowR, int nowC, int alln, int r, int c)
{
	int i,j;
	int tempR = nowR,tempC = nowC;
	if(nowC == c-1)//如果是行末尾的话
	{
		tempR++;
		tempC = -1;
	}
	tempC++;
	for (i = tempR; i < r; i++)
	{
		for (j = tempC; j < c; j++)
		{
			if(map[nowN][i][j] == 2)
			{
				if(twoWA[nowR][nowC][i][j] == -1)
				{
					continue;
				}
				else
				{
					if(checkAllMapIsAC(alln,nowR,nowC,i,j) < 2)
					{
						map[nowN][nowR][nowC] = 3;
						map[nowN][i][j] = 3;
						oneAc[nowN] = -1;
						return 2;
					}
					else
					{
						twoWA[nowR][nowC][i][j] = -1;
					}
				}
			}
		}
		tempC=0;
	}
	return -2;
}

int main()
{
	int n;//数的个数
	int r;//行
	int c;//每个数的列
	int setFlag = 1;//记录循环次数,也就是测试数据的个数
	int i,j,k;//循环temp
	int impossible = 0;
	while(1)
	{
		cin>>n>>r>>c;
		if(n==r&&r==c&&c==0)
			break;
		else
		{
			memset(map,0,sizeof(map));
			memset(twoWA,0,sizeof(twoWA));
			memset(oneAc,0,sizeof(oneAc));
			for (i = 0; i < r; i++)
			{
				for (j = 0; j < n; j++)
				{
					cin>>tempStr;
					for (k = 0; k < c; k++)
					{
						if(tempStr[k] == '.')
						{
							map[j][i][k] = 1;
						}
						else
						{
							map[j][i][k] = 2;
						}
					}
				}
			}

			printf("Test %d\n", setFlag);
			setFlag++;

			for (j = 0; j < r; j++)//判断只有一个点的任务就完成了
			{
				for (k = 0; k < c; k++)
				{
					checkAllMapIsOneAC(n,j,k);
				}
			}

			for (i = 0; i < n; i++)
			{
				if(oneAc[i] == -1)
					continue;
				for (j = 0; j < r; j++)
				{
					for (k = 0; k < c; k++)
					{
						if(j == r-1 && k == c-1)
						{
							impossible = -1;
							goto f1;
						}
						if(map[i][j][k] == 2)
						{
							if(checkAllMapIsTwoAC(i,j,k,n,r,c) == 2)
							{
								k=c;
								j=r;
							}
						}
					}
				}
			}

			for (int t = 0; t < n; t++)
			{
				if(oneAc[t] != -1)
				{
					impossible = -1;
					goto f1;
				}
			}

			for (i = 0; i < r; i++)
			{
				for (j = 0; j < n; j++)
				{
					for (k = 0; k < c; k++)
					{
						if(map[j][i][k]==1)
						{
							cout<<".";
						}
						else if(map[j][i][k]==2)
						{
							cout<<"o";
						}
						else
						{
							cout<<"#";
						}
					}
					if(j != n-1)
					cout<<" ";
				}
				cout<<endl;
			}

			f1:if(impossible == -1)
				   cout<<"impossible"<<endl;
			   impossible = 0;
		}
	}
	return 0;
}


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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值