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

来源:互联网 发布:易语言变速器源码 编辑:程序博客网 时间:2024/05/17 02:44

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

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