algorithm 题集六 (16.11.12)

来源:互联网 发布:mac 安装oracle 编辑:程序博客网 时间:2024/06/17 11:18

nyist 8 一种排序 – operator

http://acm.nyist.net/JudgeOnline/problem.php?pid=8

现在有很多长方形,每一个长方形都有一个编号,这个编号可以重复;还知道这个长方形的宽和长,编号、长、宽都是整数;现在要求按照一下方式排序(默认排序规则都是从小到大);
1.按照编号从小到大排序
2.对于编号相等的长方形,按照长方形的长排序;
3.如果编号和长都相同,按照长方形的宽排序;
4.如果编号、长、宽都相同,就只保留一个长方形用于排序,删除多余的长方形;最后排好序按照指定格式显示所有的长方形;

code:

//============================================================================// Name        : nyist.cpp// Author      : theArcticOcean// Version     :// Copyright   :// Description : C++, Ansi-style//============================================================================#include <iostream>#include <stdio.h>#include <algorithm>using namespace std;typedef struct node retangle;struct node{    int num, length, width;};bool equal (retangle self,retangle other){    if(self.num == other.num &&    self.length == other.length &&    self.width == other.width)  return 1;    return 0;}bool cmp(retangle self,retangle other){    if(self.num != other.num) return self.num < other.num;    if(self.length != other.length) return self.length < other.length;    if(self.width != other.width) return self.width < other.width;    return 1;}retangle reg[1005];int main() {    int t,m;    cin>>t;    while(t--){        scanf("%d",&m);        int i;        for(i=0;i<m;i++){            scanf("%d%d%d",&reg[i].num,&reg[i].length,&reg[i].width);            if(reg[i].length < reg[i].width) swap(reg[i].length,reg[i].width);        }        sort(reg,reg+m,cmp);        for(i=0;i<m;i++){            if(i==0){                printf("%d %d %d\n",reg[i].num,reg[i].length,reg[i].width);                continue;            }            if(equal(reg[i-1],reg[i])) continue;            printf("%d %d %d\n",reg[i].num,reg[i].length,reg[i].width);        }    }    return 0;}

搞不懂为什么下面的重载运算符代码不能通过。
相关报错:

/usr/include/c++/4.4/bits/stl_algo.h:89: error: no match foroperator<’ in ‘__a < __b’./Source/main.cpp:22: note: candidates are: bool node::operator<(retangle&) const

在本地中运行好好的,结果到了OJ就编译出错。

//============================================================================// Name        : nyist.cpp// Author      : theArcticOcean// Version     :// Copyright   :// Description : C++, Ansi-style//============================================================================#include <iostream>#include <stdio.h>#include <algorithm>using namespace std;typedef struct node retangle;struct node{    int num, length, width;    bool operator == (retangle &other)const{        if(num == other.num &&        length == other.length &&        width == other.width)  return 1;        return 0;    }    bool operator < (retangle &other)const{        if(num != other.num) return num < other.num;        if(length != other.length) return length < other.length;        if(width != other.width) return width < other.width;        return 1;    }};retangle reg[1005];int main() {    int t,m;    cin>>t;    while(t--){        scanf("%d",&m);        int i;        for(i=0;i<m;i++){            scanf("%d%d%d",&reg[i].num,&reg[i].length,&reg[i].width);            if(reg[i].length < reg[i].width) swap(reg[i].length,reg[i].width);        }        sort(reg,reg+m);        for(i=0;i<m;i++){            if(i==0){                printf("%d %d %d\n",reg[i].num,reg[i].length,reg[i].width);                continue;            }            if(reg[i-1] == reg[i]) continue;            printf("%d %d %d\n",reg[i].num,reg[i].length,reg[i].width);        }    }    return 0;}

nyist 14 会场安排问题 – struct sort

http://acm.nyist.net/JudgeOnline/problem.php?pid=14&rec=rec

描述:
学校的小礼堂每天都会有许多活动,有时间这些活动的计划时间会发生冲突,需要选择出一些活动进行举办。小刘的工作就是安排学校小礼堂的活动,每个时间最多安排一个活动。现在小刘有一些活动计划的时间表,他想尽可能的安排更多的活动,请问他该如何安排。

分析:如果事件的所占的时间段尽可能小,那么就能在时间线上多发生不同的事件。先进行结束时间的排序再进行开始时间的排序。

/* ============================================================================ Name        : 会场安排问题.c Author      : theArcticOcean Version     : Copyright   :  Description : C, Ansi-style ============================================================================ */#include <stdio.h>#include <stdlib.h>typedef struct event{    int begin, end;}Event;Event a[10005];int cmp(const void *e1,const void *e2){    Event *E1 = (Event *)e1;    Event *E2 = (Event *)e2;    if(E1->end == E2->end){        return E1->begin < E2->begin;  /*二级排序,按照开始时间从大到小,所用时间段越小越好*/    }    return E1->end > E2->end;  /*一级排序,按照结束时间从小到大*/}int max(int p1,int p2){    return p1>p2 ? p1:p2;}int main(void) {    int t,n;    scanf("%d",&t);    while(t--){        scanf("%d",&n);        int i,j;        for(i=0;i<n;i++){            scanf("%d%d",&a[i].begin,&a[i].end);        }        qsort(a,n,sizeof(Event),cmp);        int ans = 1;        int tag = a[0].end;        for(i=1;i<=n;i++){            if(a[i].begin > tag){                tag = a[i].end;                ans++;            }        }        printf("%d\n",ans);    }    return EXIT_SUCCESS;}

nyist 27 水池数目 – dfs

http://acm.nyist.net/JudgeOnline/problem.php?pid=27
大意:寻找联通块的数量,经典的深度优先搜索问题。

/* ============================================================================ Name        : 水池数目.c Author      : theArcticOcean Version     : Copyright   :  Description : C, Ansi-style ============================================================================ */#include <stdio.h>#include <stdlib.h>#include <string.h>char graph[105][105];int dx[4]={-1,1,0,0};int dy[4]={0,0,-1,1};typedef enum BOOL{FALSE = 0, TRUE } bool;bool out(int x,int y,int n,int m){    if(x<0 || x>=n) return TRUE;    if(y<0 || y>=m) return TRUE;    return FALSE;}void dfs(int x,int y,int n,int m){    if(graph[x][y] == '0') return ;    graph[x][y] = '0';    int i;    int xx,yy;    for(i=0;i<4;i++){        xx = x+dx[i];        yy = y+dy[i];        if(out(xx,yy,n,m)) continue;        dfs(xx,yy,n,m);    }}/*void show(int n,int m){    int i,j;    for(i=0;i<n;i++){        for(j=0;j<m;j++) printf("%c ",graph[i][j]);        puts("");    }}*/int main(void) {    int t;    int n,m;    scanf("%d",&t);    while(t--){        memset(graph,0,sizeof(graph));        scanf("%d%d",&n,&m);        int i,j;        char ch;        for(i=0;i<n;i++){            for(j=0;j<m;){                scanf("%c",&ch);                if(ch == '0' || ch == '1'){                    graph[i][j] = ch;                    j++;                }            }        }        int ans = 0;        for(i=0;i<n;i++){            for(j=0;j<m;j++){                if(graph[i][j] == '1'){                    ans++;                    dfs(i,j,n,m);                }            }        }        printf("%d\n",ans);    }    return EXIT_SUCCESS;}

由于bool是C++的内置数据类型,所以直接提交上面的代码会报错。改正:

typedef enum BOOL{FALSE = 0, TRUE } mybool;mybool out(int x,int y,int n,int m){    if(x<0 || x>=n) return TRUE;    if(y<0 || y>=m) return TRUE;    return FALSE;}

nyist 31 5个数求最值 – qsort

http://acm.nyist.net/JudgeOnline/problem.php?pid=31
练习此题的目的是为了试试qsort()

描述
设计一个从5个整数中取最小数和最大数的程序
输入
输入只有一组测试数据,为五个不大于1万的正整数
输出
输出两个数,第一个为这五个数中的最小值,第二个为这五个数中的最大值,两个数字以空格格开

/* ============================================================================ Name        : 5个数求最值.c Author      : theArcticOcean Version     : Copyright   : Description : C, Ansi-style ============================================================================ */#include <stdio.h>#include <stdlib.h>int cmp(const void *a,const void *b){    return *((int *)a) - *((int *)b); /* small -> big*/}int main(void) {    int a[5];    int i;    for(i=0;i<5;i++){        scanf("%d",&a[i]);    }    /* void qsort(void *base,int nelem,int width,int (*fcmp)(const void *,const void *)); */    qsort(a,5,sizeof(int),cmp);    printf("%d %d\n",a[0],a[4]);    return EXIT_SUCCESS;}

nyist 37 回文字符串 – LCS

http://acm.nyist.net/JudgeOnline/problem.php?pid=37&rec=rec

描述
所谓回文字符串,就是一个字符串,从左到右读和从右到左读是完全一样的,比如”aba”。当然,我们给你的问题不会再简单到判断一个字符串是不是回文字符串。现在要求你,给你一个字符串,可在任意位置添加字符,最少再添加几个字符,可以使这个字符串成为回文字符串

分析:将回文字符串逆序得到第二个字符串,然后求出他们的最长公共子序列,不在最长公共子序列中的字符的个数就是需要添加的字符数。

/* ============================================================================ Name        : 回文字符串.c Author      : theArcticOcean Version     : Copyright   :  Description : C, Ansi-style ============================================================================ */#include <stdio.h>#include <stdlib.h>#include <string.h>#define LEN 1005char str[LEN];char str2[LEN];int len;int dp[LEN][LEN];int max(int p1,int p2){    return p1>p2?p1:p2;}void LCS(){    memset(dp,0,sizeof(dp));    int i,j;    for(i=1;i<=len;i++){        for(j=1;j<=len;j++){            /*dp[i][j] = max(dp[i][j],dp[i][j-1]);            dp[i][j] = max(dp[i][j],dp[i-1][j]);            if(str[i] == str2[j]){                dp[i][j] = max(dp[i][j],dp[i-1][j-1]+1);            }*/            if(str[i] == str2[j]){                dp[i][j] = dp[i-1][j-1]+1;            }            else if(dp[i-1][j] > dp[i][j-1]){                dp[i][j] = dp[i-1][j];            }            else {                dp[i][j] = dp[i][j-1];            }        }    }}int main(void) {    int t;    scanf("%d",&t);    while(t--){        scanf("%s",str+1);        len = strlen(str+1);        int i;        for(i=len;i>=1;i--){            str2[len+1-i] = str[i];        }        LCS();        printf("%d\n",len-dp[len][len]);    }    return EXIT_SUCCESS;}

nyist 58 最少步数 – bfs

http://acm.nyist.net/JudgeOnline/problem.php?pid=58

描述
这有一个迷宫,有0~8行和0~8列:

1,1,1,1,1,1,1,1,1
1,0,0,1,0,0,1,0,1
1,0,0,1,1,0,0,0,1
1,0,1,0,1,1,0,1,1
1,0,0,0,0,1,0,0,1
1,1,0,1,0,1,0,0,1
1,1,0,1,0,1,0,0,1
1,1,0,1,0,0,0,0,1
1,1,1,1,1,1,1,1,1

0表示道路,1表示墙。

现在输入一个道路的坐标作为起点,再如输入一个道路的坐标作为终点,问最少走几步才能从起点到达终点?

(注:一步是指从一坐标点走到其上下左右相邻坐标点,如:从(3,1)到(4,1)。)

分析:经典的广度优先搜索问题。

/* ============================================================================ Name        : 最少步数.c Author      : theArcticOcean Version     : Copyright   :  Description : C, Ansi-style ============================================================================ */#include <stdio.h>#include <stdlib.h>#define MAX 1000000char gra[9][9]={        {1,1,1,1,1,1,1,1,1},        {1,0,0,1,0,0,1,0,1},        {1,0,0,1,1,0,0,0,1},        {1,0,1,0,1,1,0,1,1},        {1,0,0,0,0,1,0,0,1},        {1,1,0,1,0,1,0,0,1},        {1,1,0,1,0,1,0,0,1},        {1,1,0,1,0,0,0,0,1},        {1,1,1,1,1,1,1,1,1}};char vis[9][9];typedef struct point{    int x,y;}Point;int dis[10][10];int dx[4] = {-1,1,0,0};int dy[4] = {0,0,-1,1};typedef enum Bool{FALSE=0,TRUE}mybool;mybool ok(int x,int y){    if(x<0 || x>=9) return FALSE;    if(y<0 || y>=9) return FALSE;    if(vis[x][y] == 1) return FALSE;    return TRUE;}int min(int x,int y){    return x<y ? x:y;}void bfs(int a,int b,int c,int d){    Point que[90];    Point temp,next;    int head = 0,tail = 0;    next.x = a;   next.y = b;    que[tail++] = next;    while(head < tail){        temp = que[head++];        int i;        int xx,yy;        for(i=0;i<4;i++){            xx = temp.x+dx[i];            yy = temp.y+dy[i];            if(ok(xx,yy)){                next.x = xx;                next.y = yy;                dis[xx][yy] = min(dis[xx][yy],dis[temp.x][temp.y]+1);                que[tail++] = next;                vis[xx][yy] = 1;                if(xx == c && yy == d) return ;            }        }    }}int main(void) {    int t;    scanf("%d",&t);    while(t--){        int a,b,c,d;        scanf("%d%d%d%d",&a,&b,&c,&d);        int i,j;        for(i=0;i<9;i++){            for(j=0;j<9;j++){                dis[i][j] = MAX;                vis[i][j] = gra[i][j];            }        }        dis[a][b] = 0;        bfs(a,b,c,d);        printf("%d\n",dis[c][d]);    }    return EXIT_SUCCESS;}

nyist 86 找球号(一) – map or qsort+bsearch

http://acm.nyist.net/JudgeOnline/problem.php?pid=86

描述
在某一国度里流行着一种游戏。游戏规则为:在一堆球中,每个球上都有一个整数编号i(0<=i<=100000000),编号可重复,现在说一个随机整数k(0<=k<=100000100),判断编号为k的球是否在这堆球中(存在为”YES”,否则为”NO”),先答出者为胜。现在有一个人想玩玩这个游戏,但他又很懒。他希望你能帮助他取得胜利。
输入
第一行有两个整数m,n(0<=n<=100000,0<=m<=1000000);m表示这堆球里有m个球,n表示这个游戏进行n次。
接下来输入m+n个整数,前m个分别表示这m个球的编号i,后n个分别表示每次游戏中的随机整数k
输出
输出”YES”或”NO”

我觉得出题人应该提示,本体只有一组大数据。不然解题者用了while()读取就超时。
map:

//============================================================================// Name        : 找球号(1).cpp// Author      : theArcticOcean// Version     :// Copyright   :// Description : C++, Ansi-style//============================================================================#include <iostream>#include <stdio.h>#include <map>using namespace std;int main() {    int m,n;    scanf("%d%d",&m,&n);    int i, temp=0;    map<int,int> mp;    for(i=0;i<m;i++){        scanf("%d",&temp);        mp[temp] = 1;    }    for(i=0;i<n;i++){        scanf("%d",&temp);        if(mp[temp] > 0) puts("YES");        else puts("NO");    }    return 0;}

使用qsort() + bsearch():

//============================================================================// Name        : 找球号(1).cpp// Author      : theArcticOcean// Version     :// Copyright   :// Description : C++, Ansi-style//============================================================================#include <iostream>#include <stdio.h>#include <stdlib.h>using namespace std;const int len = 1e6+10;int a[len];int cmp(const void *a,const void *b){    return *((int *)a) - *((int *)b);   /* small -> greater */}int main() {    int m,n;    scanf("%d%d",&m,&n);    int i, top=0;    for(i=0;i<m;i++){        scanf("%d",&a[top++]);    }    qsort(a,top,sizeof(int),cmp);    int temp;    for(i=0;i<n;i++){        /*void *bsearch(const void *key, const void *base, size_t nmem, size_t size,int (*comp)(const void *, const void *));*/        scanf("%d",&temp);        int *ans = NULL;        ans = (int *)bsearch(&temp,a,top,sizeof(int),cmp);        if(ans == NULL) puts("NO");        else puts("YES");    }    return 0;}

nyist 96 n-1位数
http://acm.nyist.net/JudgeOnline/problem.php?pid=96
描述
已知w是一个大于10但不大于1000000的无符号整数,若w是n(n≥2)位的整数,则求出w的后n-1位的数。

输入
第一行为M,表示测试数据组数。
接下来M行,每行包含一个测试数据。
输出
输出M行,每行为对应行的n-1位数(忽略前缀0)。如果除了最高位外,其余位都为0,则输出0。

分析:简单纯模拟

/* ============================================================================ Name        : n-1位数.c Author      : theArcticOcean Version     : Copyright   :  Description : C, Ansi-style ============================================================================ */#include <stdio.h>#include <stdlib.h>#include <string.h>int main(void) {    int M;    char str[7];    scanf("%d",&M);    getchar();    while(M--){        memset(str,0,sizeof(str));        gets(str);        int len = strlen(str);        int i;        for(i=1;i<len;i++){            if(str[i] != '0') break;        }        if(i == len) puts("0");        else printf("%s\n",str+i);    }    return EXIT_SUCCESS;}

nyist 组合数 – prev_permutation

http://acm.nyist.net/JudgeOnline/problem.php?pid=32
描述
找出从自然数1、2、… 、n(0

#include <stdio.h>#include <algorithm>  using namespace std; void show(int a[],int r){      int i;      for(i=0;i<r;i++){      printf("%d",a[i]);      }      puts("");}bool check1(int a[],int b[],int r){     bool result=1;     int i=0;     for(i=0;i<r;i++){         if(a[i] != b[i]){             result=0;             break;         }     }     return result;}bool check2(int a[],int r){    int last=a[0];    int i=0;    for(i=1;i<r;i++){        if(last<a[i]) return 0;        last=a[i];    }    return 1;}int main(){    int n,r;    while(~scanf("%d%d",&n,&r)){        const int len=n;        int a[len];        int i;        for(i=0;i<len;i++){            a[i]=len-i;        }        show(a,r);        const int len2=r;        int b[len2];        for(i=0;i<len2;i++){            b[i]=a[i];        }        while(prev_permutation(a,a+n)){            if(check1(a,b,r) || !check2(a,r))   continue;            show(a,r);            for(i=0;i<len2;i++){                b[i]=a[i];            }        }    }    return 0;}

Uva 11827 Maximum GCD – ungetc

大意:给出一些数字(数字个数未知)求出最大公约数

分析:主要在于字符串处理, 相关函数:
把一个(或多个)字符退回到输入流中,可以理解成一个“计数器”。
int ungetc(int c, FILE *stream);

#include <iostream>#include <cstdio>#include <cstring>using namespace std;typedef long long LL;const int M=105;LL a[M],cnt;LL gcd(LL a,LL b){    return b==0?a:gcd(b,a%b);}int main(){    //freopen("cin.txt","r",stdin);    int t;    cin>>t;    while(getchar()!='\n');    while(t--){        char buffer;        cnt=0;        while((buffer=getchar())!='\n'){            if(buffer>='0'&&buffer<='9'){  //buffer take not useful char                 ungetc(buffer,stdin);                 scanf("%lld",&a[cnt++]);            }        }        LL maxm=0;        for(int i=0;i<cnt;i++){            for(int j=i+1;j<cnt;j++){                maxm=max(maxm,gcd(a[i],a[j]));            }        }        printf("%lld\n",maxm);    }    return 0;}

NSOJ 4681 数的长度 – log10

http://115.159.40.116/problem_show.php?pid=4681
N!阶乘是一个非常大的数,大家都知道计算公式是N!=N*(N-1)······*2*1.现在你的任务是计算出N!的位数有多少(十进制)?

分析:对数相加,Number相乘,底数取10。这样降低数值增长。
我怀疑测试的时候,给出的整数很可能会等于1000000。因为自己计算到999999就是过不了。

#include <math.h>#include <stdio.h>#define M 1000000double ans[M+10];int main(){    int n,a;    int i;    ans[1] = 0;    for(i=2;i<=M;i++){        ans[i] = ans[i-1]+log10(1.0*i);    }    scanf("%d",&n);    while(n--){        scanf("%d",&a);        printf("%d\n",(int)ans[a]+1);    }    return 0;}

LightOj Harmonic Number – log

大意:求解
Hn=1+12+13+14++1n=k=1n1k
分析:调和级数的近似计算——ln(n+1)+C
其中C是欧拉常数,近似等于0.57721566490153286060651209008240243104215933593992
但是在程序中直接用此公式误差仍然大,而用(log(1.0*n)+log(n+1.0))/2

#include <iostream>#include <cstdio>#include <cmath>using namespace std;const double C=0.57721566490153286060651209; const int N=1e6+10;double f[N];int main(){    //freopen("cin.txt","r",stdin);    f[1]=1;    for(int i=2;i<N;i++) f[i]=f[i-1]+1.0/i;    int T,n;    int ca=1;    cin>>T;    while(T--){        scanf("%d",&n);        double ans=0;        if(n<N){            printf("Case %d: %.11lf\n",ca++,f[n]);            continue;        }        ans=(log(1.0*n)+log(n+1.0))/2+C;        printf("Case %d: %.11lf\n",ca++,ans);    }    return 0;}
0 0
原创粉丝点击