前两道都是典型送分题 属于十分钟做完一两次提交就能AC的题目 但想不明白为啥解决率只在1/4左右、和最后一道个人觉得有一定难度的哈夫曼树解决率很接近 百思不得其解啊
//北邮2010计算机:题目1169:比较奇偶数个数 //(1<=n<=1000) #include <fstream> #include <iostream> using namespace std; int main() { int i, j, k, n, m; int even, odd; ifstream cin("BUPT_1169.txt");// while( cin >> n ){ even = odd = 0; for( i=0; i<n; i++ ){ cin >> m; if( m % 2 == 0 ) even++; else odd++; } if( even > odd ) cout << "NO\n"; else cout << "YES\n"; } system("pause");// return 0; }九度OJ 题目1170:找最小数
//北邮2010计算机:1170:找最小数 //(1<=n<=1000) #include <fstream> #include <algorithm> #include <iostream> using namespace std; struct NUMBER{ int x, y; }; NUMBER a[1000]; bool cmp( NUMBER a, NUMBER b ){ if( a.x == b.x ) return a.y < b.y; else return a.x < b.x; }; int main() { int i, j, k, n, m; ifstream cin("BUPT_1170.txt");// while( cin >> n ){ for( i=0; i<n; i++ ) cin >> a[i].x >> a[i].y; sort(a,a+n,cmp); cout << a[0].x << " " << a[0].y << endl; } system("pause");// return 0; }
有点难度的一道题 一行一行[或列]的单独写出该行[或列]的旋转for循环之后 再从中发现规律组合成双层循环 会更容易解决 另外需要注意扩充数组到7行7列 因为可能给定坐标过于偏右下使得实际有效旋转数据不足4或9个 这时要用扩充的0来代替
//北邮2010计算机:1171:C翻转 //(1<=n<=1000) #include <fstream> #include <memory.h> #include <iostream> using namespace std; #define N 7 int a[N][N]; int b[N][N]; void rotate( int s, int t, int x, int y ){ int i, j; if( s == 1 ){ //顺时针 for( i=0; i<t; i++ ) for( j=0; j<t; j++ ) b[x+j][y+t-1-i] = a[x+i][y+j]; for( i=0; i<t; i++ ) for( j=0; j<t; j++ ) a[x+i][y+j] = b[x+i][y+j]; }else{ //逆时针 for( i=0; i<t; i++ ) for( j=0; j<t; j++ ) b[x+t-1-j][y+i] = a[x+i][y+j]; for( i=0; i<t; i++ ) for( j=0; j<t; j++ ) a[x+i][y+j] = b[x+i][y+j]; //for( i=0; i<t; i++ ) // b[x+t-1-i][y] = a[x][y+i]; //第1列 //for( i=0; i<t; i++ ) // b[x+t-1-i][y+1] = a[x+1][y+i]; //第2列 //for( i=0; i<t; i++ ) // b[x+t-1-i][y+2] = a[x+3][y+i]; //第3列 } }; int main() { int i, j, k, n, m; int s, t, x, y, temp; ifstream cin("BUPT_1171.txt");// while( cin >> temp ){ memset(a,0,sizeof(a)); memset(b,0,sizeof(b)); a[0][0] = temp; for( i=1; i<5; i++ ) cin >> a[0][i]; for( i=1; i<5; i++ ) for( j=0; j<5; j++ ) cin >> a[i][j]; //for( i=0; i<5; i++ ){ // for( j=0; j<5; j++ ) // cout << a[i][j] << " "; // cout << endl; //} cin >> s >> t >> x >> y; rotate( s, t, x-1, y-1 ); for( i=0; i<5; i++ ){ for( j=0; j<4; j++ ) cout << a[i][j] << " "; cout << a[i][4] << endl; } } system("pause");// return 0; }
刚从RE的深渊跳出来 又入了WA的苦海 有待未来解决了 暂时先这样吧 另外我的思路并不简洁 因为我把完整二叉树都创建出来了 总觉得应该有不需要建立完整二叉树就能求解的思路
说下我的思路吧:
首先创建树的节点结构体t[2000] 然后按照权值排序 只排序一次 之后先挑出最小的两个组队 生成和节点 并将和节点置于t[1000] 之后由于和节点和原节点两个序列都不为空 于是用findMin函数找到两个有序序列的最小两个权值节点 并返回其下标号 其中原节点无疑已经排序好 而和节点由题目性质是天然升序排列的 故只需设ti和hi两个推进指针 比较两序列最小值哪个更小即可 获得这对最小权值节点后
再用processNode函数生成这对节点合并产生的新和节点 并将这对节点的p[父指针]指向该和节点的序号 之后按层次遍历生成的赫夫曼数 算出每个节点所在的层数(对某节点的路径长度刚好为其所在层数 其中根节点层数为0)故只需再对t[0]~t[n-1]即原节点序列分别求带权路径长度 最后输出其加和WPL
//北邮2010网院:1172:哈夫曼树 //(1<=n<=1000) //注:除首轮外每轮结合的要么是t.h各一 要么2个h //所有父节点都是h中的节点[即p都指向h中] #include "StdAfx.h" #include <fstream> #include <algorithm> //#include <ctime> #include <iostream> using namespace std; struct NODE{ int a; //叶节点权值 不超过100 int p, l, r; //父.左.右节点序号 存储的是t[i]的i int depth; //层数 int index; }; #define N 1000 NODE t[2*N]; //N之前记录原始节点 之后记录新生成的和节点 且和节点按生成顺序已然排序 int m[2]; int ti, hi, hl; //ti.hi分别为原序列.和序列推进下标 依此找到2个min 而hl为新生成和元素下标 int b[2*N]; //遍历用 bool cmp( NODE x, NODE y ){ return x.a < y.a; }; void findMin( int &n ){ //寻找最小的2个节点 for( int i=0; i<2; i++ ){ if( hl==N ){ //和序列为空(和序列不可能用光) m[i] = ti; ti++; }else if( ti==n ){ //t用光 m[i] = hi; hi++; }else{ //两序列都不空 从双序列中找最小值 if( t[ti].a <= t[hi].a ) { m[i] = ti; ti++; } else { m[i] = hi; hi++; } } } }; void processNode( int x, int y ){ //x.y为节点index //创建新和节点: t[hl].a = t[x].a + t[y].a; t[hl].l = t[x].index; t[hl].r = t[y].index; t[hl].index = hl; t[x].p = t[y].p = hl; //所有父节点都是h中的节点[即p都指向h中] hl++; //下标处理 }; int main() { int i, j, k, n; int WPL; ifstream cin("BUPT_1172.txt");// while( cin >> n ){ //srand(time(NULL)); //初始化随机数生成器 for( i=0; i<n; i++ ){ cin >> t[i].a; //t[i].a = 90 + rand()%10; //t[i].a = n-i; } sort(t,t+n,cmp); //初始化: ti = 0; hi = N; //当前待操作下标 hl = N; //hl为待写入新生成和元素的t[]的下标 for( i=0; i<n; i++ ){ t[i].index = i; t[i].l = t[i].r = t[i].p = -1; } for( i=0; i<n-1; i++ ){ //过2个产1个 每轮少1个待处理node 最终剩1个元素故n-1次 findMin( n ); //cout << "m:"<<m[0]<<"-"<<m[1]<<" "<<"hi="<<hi<<" hl="<<hl<<endl;// processNode( m[0], m[1] ); } t[hl-1].depth = 0; //根节点是t[hl-1] //按层次遍历: b[0] = hl - 1; int p = 0; //p=pointer int count = 0; for( i=0; i<2*n-1; i++ ){ //n个原节点(n-1)个和节点 if( t[b[i]].l!=-1 ){ p++; b[p] = t[b[i]].l; } if( t[b[i]].r!=-1 ){ p++; b[p] = t[b[i]].r; } count++; } for( i=1; i<2*n-1; i++ ){ t[b[i]].depth = t[t[b[i]].p].depth + 1; } for( i=0,WPL=0; i<n; i++ ) WPL += t[i].a * t[i].depth; cout << WPL << endl; } system("pause");// return 0; }