您的位置:首页 > 其它

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

2013-04-08 16:34 363 查看
首先说一下感受吧,适合组队做,但是一个队友因为要写实验报告没时间,于是我和另一个队友分开在宿舍做的,我负责偶数题。总体感觉代码量略大略大=。= 除了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个窗口,再给鼠标所在的点,问鼠标在哪个窗口上

思路:从后往前遍历一遍就好了。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: