今天的比赛。
今天的比赛做的很纠结,该反思一下自己为什么做的这么烂了,约瑟夫环的那个问题,反映出自己掌握知识不够全面,只要我们知道那个证明实现起来就很轻松了,可是如果不知道的话就会被卡了。Run Length Encoding 这道题题意读的很是晕,迷迷糊糊就把代码完了,自己还出了好几组数据测试都过,一交还是wa,原来自己把题意理解错了,其实这道题的叙述真的很理解的。All Discs Considered 这道题没读懂题意,自己猜的是拓扑排序,可是比赛时卡到那几个题了所以就没写,后来自己读了几遍题意,想了想还是不知道该怎么写,最后还是搜了一下解题报告才出来的。。。就看了这几道题。。。
1:自己的知识面太狭隘;2:读题不认真;3:思路不清晰,不敢写。。。唉.......以后要注意了。
http://acm.sdut.edu.cn/sdutoj/problem.php?action=showproblem&problemid=2348
这道题的题意是有两个磁盘,第一个磁盘有n1个安装包,(1--n1)第二个磁盘有n2个安装包(n1 + 1,n1 + n2),还有就是有d个依赖关系,x y x在只有y安装成功的前提下才能安装。每次安装只能安装同一个磁盘下的安装包。如果接下来的安装包和上一个不属于同一个磁盘,那么就需要改变一次,求最小改变次数。
拓扑排序,用两个队列来存储两个磁盘要处理的安装包,分先处理n1 和先处理 n2 两种情况求最小值。
#include <cstdio> #include <cstring> #include <iostream> #include <queue> #define maxn 100007 using namespace std; int d[maxn],td[maxn]; int n1,n2,dx; struct node { int v; int next; }e[maxn]; int p[maxn],len; void init() { int i; for (i = 0; i < maxn; ++i) { p[i] = -1; d[i] = td[i] = 0; } len = 0; } void insert(int x,int y) { e[len].v = y; e[len].next = p[x]; p[x] = len++; } int topsort(int mk) { int i; int ct = 1; queue<int>q[2]; for (i = 1; i <= n1 + n2; ++i) { if (td[i] == 0) { if (i <= n1) q[0].push(i); else q[1].push(i); } } while (!q[mk].empty() || !q[mk^1].empty()) { while (!q[mk].empty()) { int cur = q[mk].front(); q[mk].pop(); for (i = p[cur]; i != -1; i = e[i].next) { int pos = e[i].v; td[pos]--; if (td[pos] == 0) { if (pos <= n1) q[0].push(pos); else q[1].push(pos); td[pos] = -1; } } } //mk磁盘中无可处理安装包了 ct++; mk ^= 1; } return ct; } int main() { int i,x,y; while (scanf("%d%d%d",&n1,&n2,&dx)) { if (!n1 && !n2 && !dx) break; init(); for (i = 0; i < dx; ++i) { scanf("%d%d",&x,&y); insert(y,x); d[x]++; } for (i = 1; i <= n1 + n2; ++i) td[i] = d[i]; int l = topsort(0); for (i = 1; i <= n1 + n2; ++i) td[i] = d[i]; int r = topsort(1); printf("%d\n",min(l,r)); } return 0; }
http://acm.sdut.edu.cn/sdutoj/problem.php?action=showproblem&problemid=2351
考察约瑟夫环的优化问题 http://baike.baidu.com/view/717633.htm
m等于2时有公式http://zh.wikipedia.org/wiki/%E7%BA%A6%E7%91%9F%E5%A4%AB%E6%96%AF%E9%97%AE%E9%A2%98
#include <iostream> #include <cstdio> #include <cstring> using namespace std; char str[5]; int main() { while (scanf("%s",str)) { int a; if (!strcmp(str,"00e0")) break; int num = 0; num = num*10 + str[0] - '0'; num = num*10 + str[1] - '0'; int len = str[3] - '0'; for (int i = 0; i < len; ++i) num *= 10; for (a = 1; a < num; a *= 2) { if (num - a < a) break; } printf("%d\n",2*(num - a) + 1); } return 0; }
http://acm.sdut.edu.cn/sdutoj/problem.php?action=showproblem&problemid=2352
题目描述很操蛋。。。
就是如果出现连续的字符输出其个数以及该字符,如果大于9个只处理前九个,后面的按新的字符串处理,如果不连续,首先输出1然后输出不连续的字符序列最后在输出1 如果不连续的字符序列中有1则输出11
注意当输入字符只有1是输出1111
#include <iostream> #include <cstdio> #include <cstring> #define maxn 1007 using namespace std; char str[maxn]; int main() { //freopen("in.txt","r",stdin); int i,j; while (gets(str) != NULL) { int len = strlen(str); str[len] = '\0'; //一个是单独处理一下 if (len == 1) { if (str[0] == '1') printf("1111\n"); else printf("1%c1\n",str[0]); continue; } for (i = 0; i < len;) { if (str[i] == str[i + 1]) { //把连续的先输出 int ct = 0; for (j = i; str[j] == str[j + 1] && ct < 8; ++j,++ct) {} printf("%d%c",ct + 1,str[i]); i = j + 1; } else { //不连续的首先输出1 printf("1"); for (j = i; str[j] != str[j + 1]; ++j) {} // printf(">>>%d\n",j); for (int p = i; p < j; ++p) { //如果有1输出11 if (str[p] == '1') printf("11"); else printf("%c",str[p]); } printf("1"); i = j; } } printf("\n"); memset(str,0,sizeof(str)); } return 0; }