soj 2013 weekly-4 暨校赛模拟II 7904-7911

首先说一下感受吧,适合组队做,但是一个队友因为要写实验报告没时间,于是我和另一个队友分开在宿舍做的,我负责偶数题。总体感觉代码量略大略大=。= 除了1001这道题目看都没看,剩下的感觉还是很有思路的,就是不对~

1000

题意:经典的24点问题,不过是问能得到的最长的连续数字起终点。

思路:深搜出所有的结果,放入set中,再遍历一遍找出最长段。

#include <cstdio>
#include <set>
using namespace std;
int arr[5];
int pro[3000], pn;
set <int> S;
set<int>::iterator it;
void calc(int t[], int size)
{
	if (size == 1) S.insert(t[0]);//pro[pn++] = t[0];
	int c[5], i, j, k, l, m, n;
	for (i = 0; i < size-1; ++ i)
	{
		for (j = i+1; j < size; ++ j)
		{
			m = t[i]; n = t[j];
			for (k=0, l=0; k < size; ++ k)
				if (k!=i && k!=j) c[l++] = t[k];
			c[size-2] = m*n; calc(c,size-1);
			c[size-2] = m+n; calc(c,size-1);
			c[size-2] = m-n; calc(c,size-1);
			c[size-2] = n-m; calc(c,size-1);
			if (m!=0 && n%m==0)
			{
				c[size-2] = n/m;
				calc(c,size-1);
			}
			if (n!=0 && m%n==0)
			{
				c[size-2] = m/n;
				calc(c,size-1);
			}
		}
	}
}
int ans, st, ed, ta, tst;
int main()
{
	int Case = 1;
	while (true)
	{
		for (int i = 0; i < 4; ++ i) scanf("%d", &arr[i]);
		if (arr[0] == 0) break;
		S.clear();
		calc(arr, 4);
		for (it=S.begin(), pn=0; it!=S.end(); ++ it) pro[pn++] = *it;
		ans = st = ed = 0;
		ta = 1; tst = pro[0];
		for (int i = 1; i < pn; ++ i)
		{
			if (pro[i] == pro[i-1]+1) ta ++;
			else
			{
				if (ta >= ans)
				{
					ans = ta;
					st = tst;
					ed = pro[i-1];
				}
				ta = 1;
				tst = pro[i];
			}
		}
		if (ta >= ans)
		{
			ans = ta;
			st = tst;
			ed = pro[pn-1];
		}
		printf("Case %d: %d to %d\n", Case++, st, ed);
	}
}
1001

不知道什么题目,等题解再看题吧,杨神都说毫无思路了。

1002(WA)

题意:不好描述,大体的意思是给一种编码的方式求解码结果。

思路:很明显是一个模拟题,但是WA了,我觉得可能是在变成10,100的时候出问题了,但是这里又考虑了很久觉得没什么问题。。。

#include <iostream>
#include <set>
using namespace std;
string code;
string deco[10000];
int decn, codn;
set <string> S;
int dlength()
{
	if (decn == 0) return 1;
	int ret = 0, tmp = decn;
	while (tmp) { ret ++; tmp /= 10; }
	return ret;
}
int dindex(string s)
{
	int ret = 0;
	for (int i = 0; i < s.length(); ++ i)
		ret = ret*10 + s[i]-'0';
	return ret;
}
int main()
{
	freopen("in.txt","r",stdin);
	freopen("out.txt","w",stdout);
	int Case = 1;
	while (cin >> code && code != "0")
	{
		S.clear();
		cin >> decn;
		decn --;
		for (int i = 0; i <= decn; ++ i)
		{
			cin >> deco[i];
			S.insert(deco[i]);
		}
		cout << "Case " << Case++ << ": ";
		codn = 0;
		string pre = "";
		while (true)
		{
			int len, ind;
			if (codn >= code.length()) break;
			else if (codn == 0)
			{
				len = dlength();
				ind = dindex(code.substr(codn,len));
			}
			else
			{
				decn ++;
				len = dlength();
				ind = dindex(code.substr(codn,len));
				//cout << endl << pre << " ";
				pre = pre + deco[ind][0];
				//cout << ind << deco[ind];
				//cout <<"\n'"<< pre << "'"<<endl;
				deco[decn] = pre;
				S.insert(pre);
			}
			//cout << decn << deco[decn] << endl;
			//cout << "insert" << decn << deco[decn] << endl;
			cout << deco[ind];
			pre = deco[ind];
			codn += len;
		}
		cout << endl;
		//for (int i = 0; i < decn; ++ i)
		//	printf("(%s,%d)\n", deco[i].c_str(), i);
	}
}
1003

题意:给一排牌(N张)的初始状态(牌面朝向),给N-1个操作,把最左边的一堆牌向右翻转或者把最右边的一堆牌向左翻转,再给若干个询问,问最后得到的一摞牌的第i张牌的状态(是原来的第几张牌以及朝向)

思路:用双向队列模拟,不是我写的23333~

1004

题意:给一张岛屿的高度图,问海水多高时会把岛屿分成两个或者更多块

思路:开始我没看到一个重要的条件,就是只有在周围的海水会上升,也就是说岛的“内湖”水平面是不会上升的,于是得不到案例的结果,后来把[j][k]写成[i][j]而WA了一次囧。我的思路比较愚笨,从1到1000枚举海水高度,每次都先对海水做floodfill,再对陆地做floodfill。

#include <cstdio>
#include <queue>
#include <cstring>
using namespace std;
int g[105][105];
bool vis[105][105], sea[105][105];
int n, m;
int dir[4][2] = {{0,1},{0,-1},{1,0},{-1,0}};
struct Point
{
	int r, c;
	Point() {}
	Point(int _r, int _c): r(_r), c(_c) {}
	int height() { return g[r][c]; }
	bool visit() { return vis[r][c]; }
	void setVis() { vis[r][c] = true; }
	bool leagal() { return (r>=1&&r<=n && c>=1&&c<=m); }
	bool isSea() { return sea[r][c]; }
	void setSea() { sea[r][c] = true; }
}cur, nxt;
int floodfill()
{
	int ret = 0;
	memset(vis, 0, sizeof(vis));
	queue <Point> Q;
	for (int i = 1; i <= n; ++ i)
	{
		for (int j = 1; j <= m; ++ j)
		{
			if (!sea[i][j] && !vis[i][j])
			{
				ret ++;
				vis[i][j] = true;
				Q.push(Point(i,j));
				while (!Q.empty())
				{
					cur = Q.front();
					Q.pop();
					for (int k = 0; k < 4; ++ k)
					{
						nxt.r = cur.r + dir[k][0];
						nxt.c = cur.c + dir[k][1];
						if (nxt.leagal() && !nxt.visit() && !nxt.isSea())
						{
							Q.push(nxt);
							nxt.setVis();
						}
					}
				}
			}
		}
	}
	return ret;
}
int calc()
{
	memset(sea, 0, sizeof(sea));
	for (int i = 0; i <= m+1; ++ i)
	{
		g[0][i] = g[n+1][i] = 0;
		sea[0][i] = sea[n+1][i] = 1;
	}
	for (int i = 0; i <= n+1; ++ i)
	{
		g[i][0] = g[i][m+1] = 0;
		sea[i][0] = sea[i][m+1] = 1;
	}
	for (int i = 0; i <= 1000; ++ i)
	{
		queue <Point> Q;
		for (int j = 0; j <= n+1; ++ j)
			for (int k = 0; k <= m+1; ++ k)
				if (sea[j][k]) Q.push(Point(j,k));
		while (!Q.empty())
		{
			cur = Q.front();
			Q.pop();
			for (int j = 0; j < 4; ++ j)
			{
				nxt.r = cur.r + dir[j][0];
				nxt.c = cur.c + dir[j][1];
				if (nxt.leagal() && nxt.height()<=i && !nxt.isSea())
				{
					Q.push(nxt);
					nxt.setSea();
				}
			}
		}
		int piece = floodfill();
		if (piece > 1) return i;
		else if (piece == 0) break;
	}
	return -1;
}
int main()
{
	int Case = 1;
	while (true)
	{
		scanf("%d%d",&n,&m);
		if (n==0 && m==0) break;
		for (int i = 1; i <= n; ++ i)
			for (int j = 1; j <= m; ++ j)
				scanf("%d",&g[i][j]);
		int ans = calc();
		if (ans == -1) printf("Case %d: Island never splits.\n", Case++);
		else printf("Case %d: Island splits when ocean rises %d feet.\n", Case++, ans);
	}
}

1005

题意:定义矩阵的叉乘的运算意义,给一个矩阵,问有多少种叉乘能得到该结果。

思路:杨神说找规律就好了。。。

1006

题意:告诉一个城市有n盏红绿灯的绿灯时间黄灯时间红灯时间,m条无向路径从第i盏到第j盏的时间,求汽车从s到e的最短时间,其中,汽车启动时需要5s的时间(遇到红灯能立刻停下来,但是再启动需要5s,在起点也需要5s加速时间)。

思路:注意那些细节,再做一次dijkstra就okay了无疑,但是wa了嗯~

1007

题意:桌面给n个窗口,再给鼠标所在的点,问鼠标在哪个窗口上

思路:从后往前遍历一遍就好了。

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值