一、越学越慌
真是越学越慌,发现自己大一大二没搞事,愧为计算机人,下面说说本人今天的经历
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值等于数组所占用的内存字节数,如:
- 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("不慌不慌,全部可以补");
else
loop(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
不慌不慌,全部可以补请按任意键继续. . .
排列组合???
没错,里面用到了一个排列组合的东东,我写了一个递归,迷之递归,貌似没毛病。
写这一坨之前也百度过排列组合,但是看了两句,愚笨不懂,就打算先自己摸索了。
递归真有趣