本文主要是介绍hihocoder#1051(OJ不过),希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!
一、越学越慌
真是越学越慌,发现自己大一大二没搞事,愧为计算机人,下面说说本人今天的经历
1、怎样获得数组的长度
先看看一位老哥的代码:
#include<iostream>
using namespace std;
int main(void)
{ int n; cin >> n; int *d; int c[100]; for (int i = 0; i < n; i++) cin >> c[i]; d = c; cout << "size:" << sizeof(d)-1 << endl; return 0;}
效果如下:
至此明白,求数组长度不像求字符串一样有函数(strlen)或者’\0’结尾,我们要用sizeof数组头求,但是……
#include<stdio.h>
#include <stdlib.h>
int main()
{int d[3];int *t = d;printf("%d %d\n", sizeof(d), sizeof(t)); system("pause");
}
结果是 12 8
那么
- sizeof怎么用???
- 为什么sizeof指针长为8字节?
2、sizeof怎么用,sizeof指针是?
sizeof用法:参考自此
指针宽度问题:参考自此
数组的sizeof值等于数组所占用的内存字节数,如:
- char a1[] = “abc”;
sizeof( a1 ); // 结果为4,字符 末尾还存在一个终止符 - int a2[3];
sizeof( a2 ); // 结果为3*4=12(4的值依赖于int长度)
与上文的数组长度联系起来~~
void foo3(char a3[3])
{
int c3 = sizeof( a3 ); // c3 == 4
}
这里函数参数a3已不再是数组类型,而是蜕变成指针,相当于char* a3
为什么呢??仔细想想就不难明白,我们调用函数foo1时,程序会在栈上分配一个大小为3的数组吗不会!数组是“传址”的,调用者只需将实参的地址传递过去,所以a3自然为指针类型(char*),c3的值也就为4。
指针宽度与寻址
不同类型的变量的地址所占的字节数都是一样的,意思是什么,就是
int ,char*,double *,long *等宽度都是一样的,不信你看,在vs上试试
#include<stdio.h>
#include <stdlib.h>
int main()
{int i;int *ia = &i;printf("int : %d ", sizeof(i));printf("int * : %d \n", sizeof(ia));char c;char *ca = &c;printf("char : %d ", sizeof(c));printf("char * : %d \n", sizeof(ca));long l;long *la = &l;printf("long : %d ", sizeof(l));printf("long * : %d \n", sizeof(la));double d;double *da = &d;printf("double : %d ", sizeof(d));printf("double * : %d \n", sizeof(da));system("pause");
}
结果如下
int : 4 int * : 8
char : 1 char * : 8
long : 4 long * : 8
double : 8 double * : 8
可能有疑问了,上面的那个人文章里说char *是4个字节的,咱们我试的是8个字节呢,这就要说到计算机的寻址能力
3、32位机 64位机寻址能力与数据模型
寻址能力(参考自此)
一、什么叫寻址空间? 寻址空间一般指的是CPU对于内存寻址的能力。通俗地说,就是能最多用到多少内存的一个问题。数据在存储器(RAM)中存放是有规律的 ,CPU在运算的时候需要把数据提取出来就需要知道数据在那里 ,这时候就需要挨家挨户的找,这就叫做寻址,但如果地址太多超出了CPU的能力范围,CPU就无法找到数据了。 CPU最大能查找多大范围的地址叫做寻址能力 ,CPU的寻址能力以字节为单位。
地址总线为N位(N通常都是8的整数倍;也说N根数据总线)的CPU寻址范围是2的N次方字节,即2^N(B)。
二、16位、32位、64位通常指的是什么? 从CPU的发展史来看,从以前的8位到现在的64位,8位也就是CPU在一个时钟周期内可并行处理8位二进字符0或是1,就以此类推是64位就64位二进制.
好了,看了上面两段话差不多就是32位机可以找2^32个地址,找一空间,这个空间需要32bits来标识。32/8=4字节,那么 char *之类所占位数是4咯。
而我的机子64位,就8位了。
问题又来了,为什么,我的64位机子long类型只有4字节宽度???
数据模型 参考此博文
你去百度:数据类型宽度,有一大票会说64位下long是8位宽。
为什么???看下面这张表,这个才具体
TYPE | LP32 | ILP32 | LP64 | ILP64 | LLP64 |
---|---|---|---|---|---|
CHAR | 8 | 8 | 8 | 8 | 8 |
SHORT | 16 | 16 | 16 | 16 | 16 |
INT | 16 | 32 | 32 | 64 | 32 |
LONG | 32 | 32 | 64 | 64 | 32 |
LONG LONG | 64 | 64 | 64 | 64 | 64 |
POINTER | 32 | 32 | 64 | 64 | 64 |
windows 64位系统用的是LLP64的数据模型,明白了,这话不敢说。
这儿还有一个英文网站具体看看
二、开始做题
1、题目要求:
描述
小Ho给自己定了一个宏伟的目标:连续100天每天坚持在hihoCoder上提交一个程序。100天过去了,小Ho查看自己的提交记录发现有N天因为贪玩忘记提交了。于是小Ho软磨硬泡、强忍着小Hi鄙视的眼神从小Hi那里要来M张"补提交卡"。每张"补提交卡"都可以补回一天的提交,将原本没有提交程序的一天变成有提交程序的一天。小Ho想知道通过利用这M张补提交卡,可以使自己的"最长连续提交天数"最多变成多少天。
输入
第一行是一个整数T(1 <= T <= 10),代表测试数据的组数。
每个测试数据第一行是2个整数N和M(0 <= N, M <= 100)。第二行包含N个整数a1, a2, … aN(1 <= a1 < a2 < … < aN <= 100),表示第a1, a2, … aN天小Ho没有提交程序。
输出
对于每组数据,输出通过使用补提交卡小Ho的最长连续提交天数最多变成多少。
样例输入
3
5 1
34 77 82 83 84
5 2
10 30 55 56 90
5 10
10 30 55 56 90
样例输出
76
59
100
2、解题
- 第一个点的东西基本上没用到代码里,用函数间传递数组长度参数避免这个问题了,前面的纯属找事!!!
- 先说明,我做题不过oj,就是自己嗨的,只在自己的vs上跑,也经历没大量数据。所以,欢迎指出错误!
下面的代码输出格式不合题意,只核心功能想通
#include<stdio.h>
#include<string.h>
#include <stdlib.h>
int loop(int t, int b, int n, int a, int *N, int *flag);
int fill(int *N, int n, int m);
int count(int *N, int n);
int main()
{int t;int n, m;//长度int N[100];scanf_s("%d", &t);for (int i=0; i<t; i++){scanf_s("%d %d", &n, &m);for (int c = 0; c < n; c++)scanf_s("%d", &N[c]);fill(N, n, m);} system("pause");
}
int loop(int t, int b, int n, int a, int *N, int *flag)
//t是当前找了多少个,b是下一层递归从哪儿开始找,n是缺卡天的数组
//a是从n中选a个(a=n-m),N是原始数组
//flag是选择后元素数为a的数组,表示这几天补不了
{if (t == a){printf("如果这几天不补卡---> ");for (int c = 0; c < a; c++)printf("%d ", flag[c]);printf(" 那么最多可连续打卡%d天\n", count(flag, a)); return 0;}else{for (int i = b; i < n - a + 1 + t; i++){flag[t] = N[i];loop(t + 1, i+1,n, a, N, flag);}}
}int fill(int *N, int n, int m)//loop外的部分
{int a = n - m;int *flag= (int *)malloc(sizeof(int) * a);if (n <= m)printf("不慌不慌,全部可以补");elseloop(0, 0,n, a, N, flag);return 0;
}
int count(int *N, int n)//计算N中最长连续天数
{int leng=0, temp;leng = N[0] - 1;for (int i = 1; i < n; i++){temp = N[i] - N[i - 1] - 1;leng = temp > leng ? temp : leng;}temp = 100 - N[n - 1]-1;leng = temp > leng ? temp : leng;return leng;
}
输出如下
3
5 1
34 77 82 83 84
如果这几天不补卡---> 34 77 82 83 那么最多可连续打卡42天
如果这几天不补卡---> 34 77 82 84 那么最多可连续打卡42天
如果这几天不补卡---> 34 77 83 84 那么最多可连续打卡42天
如果这几天不补卡---> 34 82 83 84 那么最多可连续打卡47天
如果这几天不补卡---> 77 82 83 84 那么最多可连续打卡76天
5 2
10 30 55 56 90
如果这几天不补卡---> 10 30 55 那么最多可连续打卡44天
如果这几天不补卡---> 10 30 56 那么最多可连续打卡43天
如果这几天不补卡---> 10 30 90 那么最多可连续打卡59天
如果这几天不补卡---> 10 55 56 那么最多可连续打卡44天
如果这几天不补卡---> 10 55 90 那么最多可连续打卡44天
如果这几天不补卡---> 10 56 90 那么最多可连续打卡45天
如果这几天不补卡---> 30 55 56 那么最多可连续打卡43天
如果这几天不补卡---> 30 55 90 那么最多可连续打卡34天
如果这几天不补卡---> 30 56 90 那么最多可连续打卡33天
如果这几天不补卡---> 55 56 90 那么最多可连续打卡54天
5 10
10 30 55 56 90
不慌不慌,全部可以补请按任意键继续. . .
排列组合???
没错,里面用到了一个排列组合的东东,我写了一个递归,迷之递归,貌似没毛病。
写这一坨之前也百度过排列组合,但是看了两句,愚笨不懂,就打算先自己摸索了。
递归真有趣
这篇关于hihocoder#1051(OJ不过)的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!