有一周多没更新了 最近蹭课效果喜人 谌老师的操作系统课 很具有启发性 也喜欢给大家提问题 大家可以在座位上直接回答 不必站起来和举手 我第一次去听 就回答了四五个问题 感觉很过瘾 精神一直很振奋 高中的课堂就是这种感觉 可惜大学的课堂尤其数学等课程往往不给你回答题目的机会 我挺不喜欢这种一直坐在底下默默听的感觉 邓老师的数据结构课就更是非常好了 每次都收获很大 组成原理的课收获也不小 感觉比自己看书要快很多 而网络课就相对乏味了 可能是还没进入核心部分的原因?也可能是老师真的就这风格 而且我还不知道老师的姓名呢 都不方便问身边的同学其他老师的上课时间和地点 这个比较悲催
===============================================
九度OJ 题目1001:A+B for Matrices
时间限制:1 秒 内存限制:32 兆 特殊判题:否 提交:3347 解决:1429#include <iostream> #include <fstream> using namespace std; #define N 10 int a[N][N], b[N][N], c[N][N]; int main() { int i, j, k, n, m; ifstream cin("ZJU_1001.txt");// while( cin >> m >> n ){ for( i=0; i<m; i++ ) for( j=0; j<n; j++ ) cin >> a[i][j]; for( i=0; i<m; i++ ) for( j=0; j<n; j++ ){ cin >> b[i][j]; c[i][j] = a[i][j] + b[i][j]; } int row, column,count=0; for( i=0; i<m; i++ ){ row = 0; for( j=0; j<n; j++ ){ if( c[i][j] == 0 ) row++; else break; } if( row == n ) count++; } for( j=0; j<n; j++ ){ column = 0; for( i=0; i<m; i++ ){ if( c[i][j] == 0 ) column++; else break; } if( column == m ) count++; } cout << count << endl; } system("pause");// return 0; }
#include <iostream> #include <cmath> #include <fstream> using namespace std; int t; float withinT( int x, int y ){ if( abs(1.0*(x-y)) <= t ) return 0.5*(x+y); else return 0; } int main() { int i, j, k, n, m; int g1, g2, g3, gj, p; float a; cout.setf(ios::fixed); cout.setf(ios::showpoint); cout.precision(1); ifstream cin("ZJU_1002.txt");// while( cin >> p >> t >> g1 >> g2 >> g3 >> gj ){ float g13, g12, g23; g12 = withinT(g1,g2); if( g12!=0 ) a = g12; else { g13 = withinT(g1,g3); g23 = withinT(g2,g3); if( g13!=0 ){ if( g23==0 ) a = g13; else a = max(g1,max(g2,g3)); } else if( g23!=0 ) a = g23; else a = gj; } cout << a << endl; } system("pause"); return 0; }
这道题有点难度 其实就是11年考研数据结构编程题目的延伸——原题是两个长度相等的升序序列 本题的长度不一定相等
我的思路仍是考研原题的思路 并对其做了普适性的扩展:设较短的序列为a 长序列为b a的中位数的下标为mid 则用a[mid]去比较b[mid]和b[-mid](即倒数第mid个元素 仿python语法) 若a[mid]<=b[mid]则舍掉a[mid]之前的元素和b的最后mid-1个元素; 若a[mid]>=b[-mid]则舍掉a[mid]之后的元素和b的前mid-1个元素; 若以上两种情况都不满足即a[mid]>b[mid]则舍掉b的前后各mid-1个元素。 当b序列短于a序列时 再交换两者保证a总是更短的序列(含相等情况) 证明上述三种舍弃元素行为的正确性还是比较简单的 只需说明舍弃的元素中不含中位数 或者说中位数的下标不在舍弃元素可能存在的下标区间即可 暂不详述了
经过以上处理后 从while循环出来时 a元素只有2个 b则>=2个 之后再对a处理 使之只剩下一个 当a只有一个元素时 通过与b当下的中位数比较即可方便的确定公共序列的真正的中位数
我的思路的缺点之一 是while出口时a是2个元素而不是1个 如果能在while中让a只剩1个元素 则代码可以更简洁 留作以后优化吧
另外本程序中嵌入了一个用来生成1~100并随机分给a和b的调试代码 方便调试发现错误 开始提交时WA但又找不到错在哪里 后来经由这段调试代码很快发现是last round处应为3个可能分支 只考虑了前两种
#include <cstdio> #include <ctime> #include <iostream> using namespace std; #define N 1000000 int a[N], b[N], result; void swap( int &x, int &y ){ //swap要用引用符 int temp = x; x = y; y = temp; } void test( int* x, int* y, int s1, int e1, int s2, int e2 ){ int i; for( i=s1; i<=e1; i++ ) printf("%d ",x[i]); printf("\n"); for( i=s2; i<=e2; i++ ) printf("%d ",y[i]); printf("\n\n"); } int she( int* x, int* y, int s1, int e1, int s2, int e2 ){ //xlen<ylen int i, j, k, mid, slen, flag1, flag2, result; //slen=she's length while( e1 - s1 > 1 ){ //test(x,y,s1,e1,s2,e2);// mid = (s1+e1)/2; slen = (e1-s1)/2; //x为奇数个 flag1 = s2 + slen; flag2 = e2 - slen; if( x[mid] <= y[flag1] ){ //x前半<=y前半 s1 += slen; e2 -= slen; }else if( x[mid] >= y[flag2] ){ //x后半>=y后半 e1 -= slen; s2 += slen; }else{ //此时x前半>y前半 s2 += slen; e2 -= slen; } if( e1-s1 > e2-s2 ){ //当x不再是短序列时 交换xy //printf("enter\n"); int* z = x; x = y; y = z; swap(s1,s2); swap(e1,e2); } }//出口处a只有2个元素 //printf("out of while:\n"); //test(x,y,s1,e1,s2,e2);// if( e2-s2 == 1 ) //当y也只剩2元素时 return max(x[s1],y[s2]); int m = (s2+e2)/2; if( x[s1]<=y[m] && x[e1]>=y[m] ) //x俩元素分居y[m]左右 return y[m]; if( x[e1]<=y[m] ){ //x俩元素都在y[m]左侧 s1++; e2--; //此时x[s1]必然不是中位数 舍掉 }//出口时x只剩一个元素 else if( x[s1]>=y[m] ){ //x俩元素都在y[m]右侧 e1--; s2++; //此时x[e1]必然不是中位数 }//出口时x只剩一个元素 //printf("last round:\n"); //test(x,y,s1,e1,s2,e2);// int ylen = e2 - s2 + 1; m = (s2+e2)/2; if( ylen%2==0 && x[s1]<=y[m] || //b长度为偶 ylen%2!=0 && x[s1]>=y[m] ) //b长度为奇 return y[m]; else if( ylen%2==0 ) //b长度为偶 return min(x[s1],y[m+1]); else return max(x[s1],y[m-1]); } int main() { int i, j, k, m, n; //freopen("ZJU_1004.txt","r",stdin);// while( scanf("%d",&m)==1 ){ for( i=1; i<=m; i++ ) //舍弃a[0],b[0] scanf("%d",&a[i]); scanf("%d",&n); for( i=1; i<=n; i++ ) scanf("%d",&b[i]); ////调试用: //n = 100 - m; //1~100为测试数据 中位数必然是50 //srand(time(NULL)); //初始化随机数生成器 //for( i=1,j=1,k=1; i<=m; k++ ){ // if( rand()%2==0 || j==n+1 ) // { a[i] = k; i++; } // else if( j<=n ) // { b[j] = k; j++; } //} //if( j<n ) // for( i=j; i<=n; i++,k++ ) // b[i] = k; if( m < n ) result = she( a, b, 1,m,1,n); else result = she( b, a, 1,n,1,m); printf("%d\n",result); } //while(1);// return 0; }
//浙大2010:题目1005:Graduate Admission //input: //1st line: 学生数N<=4w 学校数M<=100 志愿数K<=5 //2nd line: M个学校的录取人数 //N lines: N个学生的GE GI K个志愿 #include <fstream> #include <memory.h> #include <algorithm> #include <cstdio> #include <iostream> using namespace std; struct STUDENT{ int id; //id=原始序号 int ge, gi, c[5]; //c[]=5个志愿 //int admit; //表是否被录取 }; STUDENT a[40000]; int s[300], t[300]; //s[]=录取计划人数 t[]=当前实际录取人数 int r[300][2]; //各学校分数线 int admit[100][40000]; bool cmp( STUDENT x, STUDENT y ){ int xT = x.ge+x.gi; int yT = y.ge+y.gi; if( xT == yT ) return x.ge > y.ge; else return xT > yT; } int main() { int i, j, k, m, n; int index; freopen("ZJU_1005.txt","r",stdin);// while( scanf("%d%d%d",&n,&m,&k)==3 ){ for( i=0; i<m; i++ ) scanf( "%d", &s[i] ); for( i=0; i<n; i++ ){ scanf( "%d%d", &a[i].ge, &a[i].gi ); for( j=0; j<k; j++ ) //k个志愿 scanf( "%d", &a[i].c[j] ); a[i].id = i; } //for( i=0; i<n; i++ )// // printf( "%d %d\n", a[i].ge, a[i].gi );// sort( a, a+n, cmp ); memset(t,0,sizeof(t)); for( i=0; i<n; i++ ){ for( j=0; j<k; j++ ){ index = a[i].c[j]; //index=志愿学校号 if( t[index] < s[index] ){ admit[index][t[index]] = a[i].id; t[index]++; //t[]初始=0 录取x个学生时为x if( t[index] == s[index] ){ //记录最低录取分数线 r[index][0] = a[i].ge; r[index][1] = a[i].gi; } break; } else if( a[i].ge==r[index][0] && a[i].gi==r[index][1] ){ admit[index][t[index]] = a[i].id; t[index]++; break; } } } for( i=0; i<m; i++ ) if( t[i]==0 ) printf("\n"); else{ sort(admit[i],admit[i]+t[i]); for( j=0; j<t[i]-1; j++ ) printf( "%d ", admit[i][j] ); printf( "%d\n", admit[i][t[i]-1] ); } } while(1);// return 0; }