九度OJ

考研的时候在王道论坛里面发现了九度OJ,觉得这个OJ还可以,就在上面做了一些题,目的是想对做完的题进行一些归纳与总结。时隔多年,发现九度OJ网址已经打不开了,据说是因为操作不当,数据库没了,有些可惜了。留下以下这几个题就当做纪念。

1.1016

这是一道简单题,主要要考虑到,比如说108,8,2这种类似的情况,其中8被认为是08,所以最后两位相同,输出-1。

#include <stdio.h>
#include <stdlib.h>
#include <string.h>

int main()
{
 char a[20], b[20], *p, *q;

 int k, a1, b1, len1, len2, a2, b2;

 while (scanf("%s%s%d", a, b, &k)) {

   len1 = strlen(a);
   len2 = strlen(b);
   
   a2 = atoi(a);
   b2 = atoi(b);
   
   if (a2 == 0 && b2 == 0) break;
   if (len1 < k) p = a;
   else p = &a[len1-k];
   if (len2 < k) q = b;
   else q = &b[len2-k];

   a1 = atoi(p);
   b1 = atoi(q);

   if (a1 == b1) printf("-1\n");
   else printf("%d\n", a2 + b2);
 }

 return 0;
}

2.1011

#include <stdio.h>
/****
***** 没有做比较 简单的把相加的和小于零就丢掉,正确的方法应该要保存起来
******/
int min(int x, int y)
{
 return x > y ? y : x;
}

int abs(int x)
{
 return -x;
}

int main()
{
 int k, s, t, i, j, flag, max, index;
 int a[11000];
 int svalue, tvalue, value;
 int mi;

 while (scanf("%d", &k), k) {
  flag = 0;
  max = -1;
  for (i = 0; i < k; i++) {
   scanf("%d", &a[i]);
   if (a[i] > 0) flag = 1;
  }
  if (!flag) {
   printf("0 %d %d\n", a[0], a[k-1]);
   continue;
  }

  i = s = 0;
  value = 0;
  j = t = k - 1;
  svalue = tvalue = 0;
  
  while (i < j) {
   svalue += a[i];
   tvalue += a[j];

   if (svalue < 0) {//如果小于零,丢掉这一段
    s = i + 1;
    svalue = 0;
   }

   if (tvalue <= 0) {
    t =  j - 1;
    tvalue = 0;
   }

   i++;
   j--;
  }

  if (i == j) {
   mi = min(svalue, tvalue);
   if (a[i] < 0) {
    if (abs(a[i]) > svalue && abs(a[i]) < tvalue) {
     s = i + 1;
    } else if (abs(a[i]) > svalue && abs(a[i]) > tvalue)

{
     if (svalue >= tvalue) {
      t = j - 1;
     } else {
      s = i + 1;
     }
    } else if (abs(a[i]) < svalue && abs(a[i]) >= tvalue)

{
     t = j - 1;
    }
   }
  }
  
  for (i = 0; i <k; i ++) {
   if (a[i] > max)  {
    index = i;
    max = a[i];
   }
  }

  for (i = s; i <=t; i++) value += a[i];

  if (max > value) {//找出序列最大的元素
   printf("%d %d %d\n", max, a[index], a[index]);
   
  } else printf("%d %d %d\n", value, a[s], a[t]);
 }
 return 0;
}

正确的做法

#include <iostream>

using namespace std;

int dig[10100];
int main()
{
int n;
while(cin>>n&&n)
{
for(int i=0;i<n;i++)
cin>>dig[i];

int num=0;
for(int i=0;i<n;i++)
if(dig[i]<0)
num++;

if(num==n)
cout<<0<<" "<<dig[0]<<" "<<dig[n-1]<<endl;

else
{
int start=0,end=0,max=-9999,sum=0;
for(int i=0,k=0;i<n;i++)
{
sum+=dig[i];
if(sum>max) {max=sum;start=k;end=i;}//保存每次的最大值,在最大值中选出最大值
if(sum<0) {sum=0;k=i+1;}
}
cout<<max<<" "<<dig[start]<<" "<<dig[end]<<endl;
}

}
return 0;
}

3.1008

首先要说的是这题数据很特殊,有重边,是个天坑。

#include <set>
#include <map>
#include <list>
#include <cmath>
#include <ctime>
#include <deque>
#include <queue>
#include <stack>
#include <cstdio>
#include <string>
#include <vector>
#include <cctype>
#include <cstring>
#include <sstream>
#include <fstream>
#include <cstdlib>
#include <cassert>
#include <iostream>
#include <algorithm>
 
using namespace std;
//Constant Declaration
/*--------------------------*/
//#define LL long long
#define LL __int64
const int M=1100;//最多点数
const int INF=1<<30;
const double EPS = 1e-11;
const double PI = acos(-1.0);
/*--------------------------*/
// some essential funtion
/*----------------------------------*/
void Swap(int &a,int &b){   int t=a;a=b;b=t; }
int Max(int a,int b){   return a>b?a:b;  }
int Min(int a,int b){   return a<b?a:b;  }
int Gcd(int a,int b){   while(b){b ^= a ^=b ^= a %= b;}  return a; }
/*----------------------------------*/
//for (i = 0; i < n; i++)
/*----------------------------------*/


int d[M][M], p[M][M];//存放距离和花费
int min_d[M], min_p[M];//存放最小距离和最小花费
int u[M];//保存u中的节点


void init(int n)
{
 int i, j;

 for (i = 1; i <= n; i++) {
  for (j = 1; j <= n; j++) {
   d[i][j] = INF;
   p[i][j] = INF;
  }
 }

 for (i = 1; i <= n; i++) {
  min_d[i] = INF;
  min_p[i] = INF;
 }

 memset(u, 0, sizeof(u));
}

int dijkstra(int s, int t, int n)
{
 int i;//用来做计数
 
 int mid;//中间节点

 min_d[s] = 0;//起点到起点的距离为0
 min_p[s] = 0;//花费也为0

 for (int cnt = 0; cnt < n; cnt++) {
   int min = INF;
      for (i = 1; i <= n; i++) {

    if (!u[i] && min_d[i] < min) {//保证是u中的节点
     min = min_d[i];
     mid = i;
    }
   }
   u[mid] = 1;
   
   for (i = 1; i <= n; i++) {
    if (!u[i] && (min_d[mid] + d[mid][i]) < min_d[i]) {
      min_d[i] = min_d[mid] + d[mid][i];
      min_p[i] = min_p[mid] + p[mid][i];
    }

    if ((min_d[mid] + d[mid][i]) == min_d[i] &&
     (min_p[mid] + p[mid][i]) < min_p[i]) {
     min_p[i] = min_p[mid] + p[mid][i];
    }
   }
 }
 return 0;
}

int main()
{
 
 int n, m, s, t;//分别为节点数,边数,起点编号,终点编号


 //输入
 while (scanf("%d%d", &n, &m), n + m) {
  init(n);

  int a, b, c, c1;//用来接收每一条边的信息
  int i;//用来计数

  for (i = 0; i < m; i++) {

   scanf("%d%d%d%d", &a, &b, &c, &c1);

   if (d[a][b] > c) {
    d[a][b] = d[b][a] = c;
    p[a][b] = p[b][a] = c1;
   }//无向图

   if (d[a][b] == c && p[b][a] > c1) {//输入有重边
    p[b][a] = p[a][b] = c1;
   }
  }

  scanf("%d%d", &s, &t);
  dijkstra(s, t, n);
  printf("%d %d\n", min_d[t], min_p[t]);

 }

 return 0;

}

4.1012和1017

1012和1017都是畅通工程问题,1012是并查集问题,1017是最小生成树问题,可以用普里姆算法和克鲁斯卡尔算法来求,用克鲁斯卡尔的时候判断环有点困难,有人用并查集算法来判断有无环。

5.1015

这是一道简答题,用qsort函数很容易就能搞定,qsort的第二个参数多少个元素参与排序,一定不要写错了。还有就是记得初始化,如果不初始化用qsort函数很容易产生错误。

#include <stdio.h>
#include <stdlib.h>
#include <string.h>

struct student {
 char id[30];
 int count;
 int ques[20];
 int grade;
}stu[1010];

int point[1010];
int cnt;

int comp(const void *a, const void *b)
{
 int res;

 struct student *p = (struct student *)a;
 struct student *q = (struct student *)b;

 if ((p->grade) == (q->grade)) {//如果成绩一样,按照名字的字母表排序
   res = strcmp(p->id, q->id);
   return res;

 } return q->grade - p->grade;
}

int init()//初始化
{
 int i;
 cnt = 0;

 for (i = 0; i < 1010; i++) {
  stu[i].grade = 0;
  stu[i].count = 0;
  memset(stu[i].id, 0, 30);
  memset(stu[i].ques, 0, 20);
 }

 return 0;
}

int main()
{
 int n, m, g, i, j;

 while (scanf("%d", &n), n) {
  scanf("%d%d", &m, &g);
  init();

  for (i = 1; i <=m; i++) {
   scanf("%d", &point[i]);
  }

  for (i = 0; i < n; i++) {
   scanf("%s", stu[i].id);
   scanf("%d", &stu[i].count);
   
   for (j = 0; j < stu[i].count; j++) {
    scanf("%d", &stu[i].ques[j]);
   }

   for (j = 0; j < stu[i].count; j++) {
    stu[i].grade += point[stu[i].ques[j]];
   }

   if (stu[i].grade >= g) cnt++;
  }
   qsort(stu, n, sizeof(struct student), comp);
   
   printf("%d\n", cnt);

   for (i = 0; i < cnt; i++) {
    printf("%s %d\n", stu[i].id, stu[i].grade);
   }
 }
 return 0;
}

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值