文章目录

  • (1)递归
  • ① 选择法排序【P63】
  • ② 冒泡法排序【P65】
  • ③ 全排列【P175】
  • ④ Fibonacci 数列
  • (2)分治法
  • ① 快速排序【P86】
  • ② 归并排序【P88】
  • ③ 查找最大值和次大值问题【P91】
  • ④ 折半查找【P93】
  • ⑤ 2019 年女排世界杯,一共 12 个队伍进行比赛,比赛形式是:单循环赛制。也就是每个队伍之间进行有且仅有一场比赛,编写程序,输入 k 个队伍,输出对应的对阵表例如 k 等于 4,表示 4 个队伍。单循环赛的赛程如下。【P106】
  • (3)蛮力法
  • ① 选择法排序【注意是蛮力法的书写】【P125】
  • ② 冒泡法排序【注意是蛮力法的书写】【P127】
  • ③ 最大值连续子序问题【P129】
  • ④ 背包问题:【此题要求掌握纯蛮力法书写和深度优先算法书写】【P135 页】
  • (4)回朔法
  • ① 设计一个算法在 1,2,……9(顺序不变)【P172 页】
  • ② 0 和 1 背包问题【使用回朔法解决】【P178 页】
  • ③ 活动安排问题【P198 页】
  • ④ 迷宫问题 【P154 页】
  • (5)贪心法
  • ① 顾客在超市购买物品一共消费 x 元【任意输入 x 的值,x 的值在 1 到 100 之间,、并且是整数】。支付的纸币为 100 元,计算超市收银员应找回顾客多少钱?【告知前提所有的纸币数量充足下,纸币包含面额是 100 元、50 元、20 元、5 元、1 元】
  • ② 柠檬水找零
  • ③ 简单背包问题【P251 页】
  • ④ 求解活动安排问题【P246】
  • (6)动态规划
  • ① 使用动态规划发,求 fibonacci 数列。【P282】
  • ② 求解整数拆分问题。【P291】
  • ③ 求解 0/1 背包问题【P307】
  • ④ 最长公共子序列【P299】

(1)递归

① 选择法排序【P63】

思路
有n个数,乱序。
第一次,遍历找到最小数字,与第一个交换。
第二次,从第二个数字出发,遍历找到最小数字,与第二个交换。
第三次,从第三个数字出发,遍历找到最小数字,与第三个交换。

直到用来记录出发位置的数字(begin)累加到等于数组长度(n-1),完成。

完整代码

#include<iostream>

using namespace std;

void swap(double *p, double *q) { double t = *p; *p = *q; *q = t; }

void selectsort(int a[],int n,int begin)
{
    if(begin==n-1)return;
    
    int u=begin,minn=a[begin];
    
    for(int i=begin+1;i<n;i++)
        if(minn>a[i])minn=a[i],u=i;
    
    if(begin!=u)swap(&a[u],&a[begin]);
    
    selectsort(a,n,begin+1);
}

int main()
{
	double a[1000];
	int n;
	cin >> n;

	for (int i = 0; i < n; i++)cin >> a[i];


	selectsort(a, n, 0);
	for (int i = 0; i < n; i++)cout<< a[i]<<" ";

	return 0;
}

测试

输入

500 
    218 97 78 13 7 259 14 90 86 460 72 134 458 2 245 490 126 33 355 171 166 433 16 74 436 167 5 296 350 148 146 279 230 467
    182 31 315 77 151 442 253 224 156 325 379 183 30 47 129 124 441 497 314 193 390 463 80 362 461 280 383 185 415 179 174
    234 214 1 199 244 249 398 473 136 394 349 369 63 83 356 440 363 219 484 330 425 465 176 125 269 289 312 162 451 480
    100 342 418 243 177 149 10 422 42 478 338 141 367 346 271 221 283 114 443 216 145 235 220 380 204 147 24 307 285 403
    175 256 477 305 165 416 420 255 227 211 427 370 223 195 9 69 264 35 17 38 384 56 329 300 246 178 203 39 471 55 46 
    103 263 455 231 487 445 188 268 482 58 294 257 449 391 500 392 479 261 492 96 267 88 116 494 206 43 262 71 180 120 
    142 351 29 340 130 310 57 431 226 276 6 437 187 447 270 345 66 374 210 133 348 215 242 419 469 435 37 331 84 59 28 
    117 430 426 488 222 399 452 448 273 158 150 170 40 110 217 229 232 76 303 382 241 275 108 366 409 499 26 311 302 
    486 91 347 334 94 358 491 196 107 360 401 292 191 4 297 475 378 298 236 389 22 359 233 163 212 92 53 288 472 476 
    327 153 278 99 483 115 143 407 205 344 498 316 132 8 190 181 113 160 317 410 48 60 105 127 239 250 400 70 213 377 
    154 474 319 322 495 44 397 62 313 411 393 164 496 111 51 291 429 172 470 168 54 157 225 208 20 328 417 106 324 135 
    489 240 326 64 265 404 450 318 98 444 237 308 104 352 155 438 396 152 293 25 371 68 408 432 112 301 73 11 128 354 
    251 254 87 434 247 34 332 252 192 258 323 412 341 12 385 45 65 228 357 466 281 49 194 284 137 406 372 485 454 123 
    36 169 209 41 140 353 299 375 402 320 121 459 457 138 75 421 144 274 339 93 207 197 82 61 200 287 364 102 266 50 
    260 343 373 81 456 198 202 173 388 85 282 23 290 386 333 446 424 189 462 95 468 286 335 361 295 321 368 186 413 101
    67 131 89 79 439 481 122 118 387 139 27 18 395 52 423 405 381 336 184 414 3 428 119 309 493 453 161 306 15 464 248 
    109 21 365 376 32 19 272 201 238 159 337 304 277

输出

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43
 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 
 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 
 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 
 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 
 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 
 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 
 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 
 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 
 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 
 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 
 349 350 351 352 353 354 355 356 357 358 359 360 361 362 363 364 365 366 367 368 369 370 371 372 373 374 375 376 377 
 378 379 380 381 382 383 384 385 386 387 388 389 390 391 392 393 394 395 396 397 398 399 400 401 402 403 404 405 406 
 407 408 409 410 411 412 413 414 415 416 417 418 419 420 421 422 423 424 425 426 427 428 429 430 431 432 433 434 435 
 436 437 438 439 440 441 442 443 444 445 446 447 448 449 450 451 452 453 454 455 456 457 458 459 460 461 462 463 464 
 465 466 467 468 469 470 471 472 473 474 475 476 477 478 479 480 481 482 483 484 485 486 487 488 489 490 491 492 493 
 494 495 496 497 498 499 500

② 冒泡法排序【P65】

思路
有n个数,乱序。
第一次,从左往右相邻之间的数字逐格比较大小,如果a[i]<a[i+1],则交换a[i]和a[i+1]的数值,此时队尾数值必定为数列最大值,因此在下一次比对中我们可以不考虑队尾数值。
第二次,从左往右相邻之间的数字逐格比较大小,如果a[i]<a[i+1],则交换a[i]和a[i+1]的数值,此时队尾-1数值必定为数列第二最大值,因此在下一次比对中我们可以不考虑该数值。

直到所有数值都被逆序清除完毕,表明找到了第一最大值,第二最大值,大三最大值…完成。

时间复杂度
o(n^2)

核心代码

方式一

void BubbleSort(int a[],int end)//a[]数组,end队尾(长度)
{
    if(end==0)return;//直到所有数值都被逆序清除完毕,表明找到了第一最大值,第二最大值,大三最大值...完成。
    
    for(int i=0;i<end;i++)
        if(a[i]>a[i+1])swap(a[i],a[i+1]);//从左往右相邻之间的数字逐格比较大小,如果a[i]<a[i+1],则交换a[i]和a[i+1]的数值
    
    BubbleSort(a,end-1);//在下一次比对中我们可以不考虑队尾数值,清除队尾
}

方式三

void BubbleSort(int a[],int n)
{
    for(int i=0;i<n;i++)
        for(int j=0;j<n-i;j++)//根据思路我们比对一次循环之后第n个必为最大值,因此我们只需比对n次循环即可完成。
            if(a[j]>a[j+1])
                swap(&a[j],&a[j+1]);
}

方式二

void BubbleSort(int a[],int n)
{
    for(int i=0;i<n;i++)
        for(int j=i+1;j<n;j++)//与方式二并无差别,只是更换为了ij比较,实际也是a[i]比a[i+1],执行n次循环
            if(a[i]>a[j])
                swap(&a[i],&a[j]);
}

方便拿的完整代码

#include<iostream>

using namespace std;

void swap(int *a,int *b){int t=*a;*a=*b;*b=t;}

void BubbleSort(int a[],int end)
{
    if(end==0)return;
    
    for(int i=0;i<end;i++)
        if(a[i]>a[i+1])swap(a[i],a[i+1]);
    
    BubbleSort(a,end-1);
}

int main()
{
    int a[1000];
    int n;
    
	cin >> n;

	for (int i = 0; i < n; i++)cin >> a[i];


	BubbleSort(a,n-1);
	for (int i = 0; i < n; i++)cout<< a[i]<<" ";

	return 0;
}

③ 全排列【P175】

图示

[算法课]算法考试复习范围全解_数组


思路

通过二叉树的先序遍历走并且回溯

重要的是弄清走法与怎么样交换达到全排列不重不漏的目的

AC代码

#include<iostream>

using namespace std;

void dfs(int a[],int n,int i)
{
    if(i==n){for(int i =0;i<n;i++)cout<<a[i];cout<<endl;return ;}

    //如果是123全排列的话。
    //第一层是a[0]到a[0]到a[2]交换
    //第一层是a[1]到a[1]到a[2]交换
    for(int j=i;j<n;j++)
    {
        swap(a[i],a[j]);
        dfs(a,n,i+1);
        swap(a[i],a[j]);
    }

}

④ Fibonacci 数列

例2 输入n的值,求得并输出第n个fibonacci数列的数值。
已知某个数列的第1个数和第2个数的值都是1,从第3个数值开始,每个数值等于其前2个之和。

解法1.递推

#include<iostream>

using namespace std;

const int N=1e5+10;
int f[N]={0,1,1};

int main()
{
    int n;
    cin>>n;
    
    for(int i=3;i<=n;i++)f[i]=f[i-1]+f[i-2];
    
    cout<<f[n];

    return 0;
}

二叉树递归

#include<iostream>

using namespace std;

int fib(int n)
{
    if(n==1||n==2)return 1;
    else return fib(n-1)+fib(n-2);
}

int main()
{
    int n;
    cin>>n;
    cout<<fib(n);

    return 0;
}

(2)分治法

① 快速排序【P86】

题目思路
1.设立中间值为标记值
2.左右两个指针往中间走,
2.1.如果左边指针走到了的值大于标记值,停止
2.2.如果右边指针走到了的值小于标记值,停止
3.交换两个值
4.知道指针重合或者越界停止
5.确保此时左半部分小于标记值,右半部分大于标记值
6.分治递归

题目代码

#include<iostream>
#include<cstring>

using namespace std;
const int N=1E5+10;

void swap(int &a,int &b){a^=b^=a^=b;}//交换

void quick_sort(int a[],int l,int r)//快排 a数组 l左指针 r右指针
{
    if(l==r)return;//退出
    
    int i=l-1,j=r+1,x=a[l+r>>1];//因为下面是dowhile所以i,j是两边的值,a[l+r>>1]取中间值为标记值
    
    while(i<j)//ij未重合
    {
        do i++;while(a[i]<x);//找到左半部分大于标记值的值
        do j--;while(a[j]>x);//找到右半部分小于标记值的值
        if(i<j)swap(a[i],a[j]);//交换
    }
    
    quick_sort(a,l,j),quick_sort(a,j+1,r);//分治递归
}

int main()
{
    int n;
    cin>>n;
    
    int a[N];
    memset(a,0,sizeof a);
    for(int i=0;i<n;i++)cin>>a[i];
    
    quick_sort(a,0,n-1);
     
    for(int i=0;i<n;i++)cout<<a[i]<<" ";
    
    return 0;
}

② 归并排序【P88】

归并排序

图示

[算法课]算法考试复习范围全解_i++_02

时间复杂度
n(nlog2^n)

思路

持续递归将数组拆分为大小为1的块。
1.每两个大小为1的块相互比较比较数值大小,数值小的块内元素放入到临时数组TMP,循环直到某个块内元素都被循环完毕,此时另一个块内元素全部放入临时数组TMP,到此时两个块内元素都被放入临时数组TMP,TMP内为顺序递增,复制到a[]数组的l,r制定区间内部,使得a[l.r]为顺序递增,回溯到上一层。
2.每两个大小为2的块相互比较比较数值大小,数值小的块内元素放入到临时数组TMP,循环直到某个块内元素都被循环完毕,此时另一个块内元素全部放入临时数组TMP,到此时两个块内元素都被放入临时数组TMP,TMP内为顺序递增,复制到a[]数组的l,r制定区间内部,使得a[l.r]为顺序递增,回溯到上一层。
3.每两个大小为4的块相互比较比较数值大小,数值小的块内元素放入到临时数组TMP,循环直到某个块内元素都被循环完毕,此时另一个块内元素全部放入临时数组TMP,到此时两个块内元素都被放入临时数组TMP,TMP内为顺序递增,复制到a[]数组的l,r制定区间内部,使得a[l.r]为顺序递增,回溯到上一层。

直到所有元素都被检查一遍,完成

核心代码

void merge_sort(int a[],int t[],int l,int r)
{
    if(l>=r)return;//l,r指向统一个元素,或者l>r,退出条件
    
    int mid=l+r>>1;//指向了中间
    merge_sort(a,t,l,mid),merge_sort(a,t,mid+1,r);//分治递归
    
    int i=l,j=mid+1,n=0;//划分为a[l,mid],b[mid+1,r]两个部分
    while(i<=mid&&j<=r)//两个数组中同位比对,最小的数字读入到临时数组t
        if(a[i]<=a[j])t[n++]=a[i++];
        else t[n++]=a[j++];
    
    while(i<=mid)t[n++]=a[i++];//当一个数组被排完,直接读入另一个数组
    while(j<=r)t[n++]=a[j++];
    
    for(int i=0,j=l;j<=r;i++,j++)a[j]=t[i];//放入a[]数组制定的a[l,r]区域内
}

方便拿的完整代码

#include<iostream>

using namespace std;
const int N=1e5+10;
int a[N],t[N];

void merge_sort(int a[],int t[],int l,int r)
{
    if(l>=r)return;
    
    int mid=l+r>>1;
    merge_sort(a,t,l,mid),merge_sort(a,t,mid+1,r);
    
    int i=l,j=mid+1,n=0;
    while(i<=mid&&j<=r)
        if(a[i]<=a[j])t[n++]=a[i++];
        else t[n++]=a[j++];
    
    while(i<=mid)t[n++]=a[i++];
    while(j<=r)t[n++]=a[j++];
    
    for(int i=0,j=l;j<=r;i++,j++)a[j]=t[i];
}

int main()
{
    int n;
    cin>>n;
    
    for(int i=0;i<n;i++)cin>>a[i];
    
    merge_sort(a,t,0,n-1);
    
    for(int i=0;i<n;i++)cout<<a[i]<<" ";
    
    return 0;
}

③ 查找最大值和次大值问题【P91】

事实上在46页

思路
&方便传回值
&同时传值给lmaxFis,lmaxSec,rmaxFis,rmaxSec
分治细化到元素数量为1,更新最大值,
分治细化到元素数量为2,更新最大最小值,
分治细化到元素数量 >2, 比较更新两块的最大最小值

代码

解法1.二分递归

#include<iostream>

using namespace std;

int nums[]={2,5,1,4,6,3};
int a,b;

void get(int l,int r,int &a,int &b)
{
    if(l==r)
    {
        if(nums[l]>a)b=a,a=nums[l];
        else b=max(nums[l],b);
        return ;
    }
    int mid = l+r>>1;
    get(l,mid,a,b),get(mid+1,r,a,b);    
}

int main()
{
    get(0,sizeof nums/4,a,b);
    
    cout<<a<<" "<<b;
    
    return 0;
}

了解更多
这道题目的原本代码十分繁杂,宛如裹脚布一般,如果你希望更深一步了解你可以查看我写的[分治]查找最大和次大元素,或者在B站寻找优质视频进行学习

④ 折半查找【P93】

查找分类
(1)顺序查找
(2)折半查找

(1)顺序查找
思路:将所要查询的数据和已经存在的所有数据进行依次比对,如果相同则找到

(2)折半查找
提前:必须是对有序(升序还是降序)的数据进行查询。否则不能进行折半查找!【灵魂所在】

思路:
对有序的数值,求中间值,判断这个中间是否是所要查询的对象,如果是则输出,
如果不是所要查找的对象
则立即比较大小
如果中间值小于查找值,则继续再右边进行查找
如果中间值大于查找值,则继续再左边进行查找
一直重复下去。【明显能体现出 分治法的思路】
举例说明


假设找8 a[0] a[1] a[2] a[3] a[4] a[5] a[6] a[7] a[8] 原始数据 1 2 3 4 5 6 7 8 9 第1次折半查找 1 2 3 4 5 6 7 8 9 第2次折半查找 6 7 8 9 第2次折半查找 8 9 找到了 一共进行3次


思路
简单的递归,二分

代码

#include<iostream>
#include<algorithm>

using namespace std;

const int N=1e5;
int a[N],t[N];

int binnarySearch(int l,int r,int x)
{
    int mid = l+r>>1;
    int midNum = a[mid];
    
    if(midNum == x)return mid+1;
    
    if(x>midNum)binnarySearch(mid+1,r,x);
    else binnarySearch(l,mid-1,x);
}
int main()
{
    int n,x;
    cin>>n>>x;
    
    for(int i=0;i<n;i++)cin>>a[i];
    
    sort(a,a+n);
    
    cout<<binnarySearch(0,n-1,x);
    
    return 0;
}

测试数据

500 277
    218 97 78 13 7 259 14 90 86 460 72 134 458 2 245 490 126 33 355 171 166 433 16 74 436 167 5 296 350 148 146 279 230 467
    182 31 315 77 151 442 253 224 156 325 379 183 30 47 129 124 441 497 314 193 390 463 80 362 461 280 383 185 415 179 174
    234 214 1 199 244 249 398 473 136 394 349 369 63 83 356 440 363 219 484 330 425 465 176 125 269 289 312 162 451 480
    100 342 418 243 177 149 10 422 42 478 338 141 367 346 271 221 283 114 443 216 145 235 220 380 204 147 24 307 285 403
    175 256 477 305 165 416 420 255 227 211 427 370 223 195 9 69 264 35 17 38 384 56 329 300 246 178 203 39 471 55 46 
    103 263 455 231 487 445 188 268 482 58 294 257 449 391 500 392 479 261 492 96 267 88 116 494 206 43 262 71 180 120 
    142 351 29 340 130 310 57 431 226 276 6 437 187 447 270 345 66 374 210 133 348 215 242 419 469 435 37 331 84 59 28 
    117 430 426 488 222 399 452 448 273 158 150 170 40 110 217 229 232 76 303 382 241 275 108 366 409 499 26 311 302 
    486 91 347 334 94 358 491 196 107 360 401 292 191 4 297 475 378 298 236 389 22 359 233 163 212 92 53 288 472 476 
    327 153 278 99 483 115 143 407 205 344 498 316 132 8 190 181 113 160 317 410 48 60 105 127 239 250 400 70 213 377 
    154 474 319 322 495 44 397 62 313 411 393 164 496 111 51 291 429 172 470 168 54 157 225 208 20 328 417 106 324 135 
    489 240 326 64 265 404 450 318 98 444 237 308 104 352 155 438 396 152 293 25 371 68 408 432 112 301 73 11 128 354 
    251 254 87 434 247 34 332 252 192 258 323 412 341 12 385 45 65 228 357 466 281 49 194 284 137 406 372 485 454 123 
    36 169 209 41 140 353 299 375 402 320 121 459 457 138 75 421 144 274 339 93 207 197 82 61 200 287 364 102 266 50 
    260 343 373 81 456 198 202 173 388 85 282 23 290 386 333 446 424 189 462 95 468 286 335 361 295 321 368 186 413 101
    67 131 89 79 439 481 122 118 387 139 27 18 395 52 423 405 381 336 184 414 3 428 119 309 493 453 161 306 15 464 248 
    109 21 365 376 32 19 272 201 238 159 337 304 277

输出

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 
22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 
40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 
58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 
76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 
94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 
109 110 111 112 113 114 115 116 117 118 119 120 121 
122 123 124 125 126 127 128 129 130 131 132 133 134 
135 136 137 138 139 140 141 142 143 144 145 146 147 
148 149 150 151 152 153 154 155 156 157 158 159 160 
161 162 163 164 165 166 167 168 169 170 171 172 173 
174 175 176 177 178 179 180 181 182 183 184 185 186 
187 188 189 190 191 192 193 194 195 196 197 198 199 
200 201 202 203 204 205 206 207 208 209 210 211 212 
213 214 215 216 217 218 219 220 221 222 223 224 225 
226 227 228 229 230 231 232 233 234 235 236 237 238 
239 240 241 242 243 244 245 246 247 248 249 250 251 
252 253 254 255 256 257 258 259 260 261 262 263 264 
265 266 267 268 269 270 271 272 273 274 275 276 277 
278 279 280 281 282 283 284 285 286 287 288 289 290 
291 292 293 294 295 296 297 298 299 300 301 302 303 
304 305 306 307 308 309 310 311 312 313 314 315 316 
317 318 319 320 321 322 323 324 325 326 327 328 329 
330 331 332 333 334 335 336 337 338 339 340 341 342 
343 344 345 346 347 348 349 350 351 352 353 354 355 
356 357 358 359 360 361 362 363 364 365 366 367 368 
369 370 371 372 373 374 375 376 377 378 379 380 381 
382 383 384 385 386 387 388 389 390 391 392 393 394 
395 396 397 398 399 400 401 402 403 404 405 406 407 
408 409 410 411 412 413 414 415 416 417 418 419 420 
421 422 423 424 425 426 427 428 429 430 431 432 433 
434 435 436 437 438 439 440 441 442 443 444 445 446 
447 448 449 450 451 452 453 454 455 456 457 458 459 
460 461 462 463 464 465 466 467 468 469 470 471 472 
473 474 475 476 477 478 479 480 481 482 483 484 485 
486 487 488 489 490 491 492 493 494 495 496 497 498 
499 500

⑤ 2019 年女排世界杯,一共 12 个队伍进行比赛,比赛形式是:单循环赛制。也就是每个队伍之间进行有且仅有一场比赛,编写程序,输入 k 个队伍,输出对应的对阵表例如 k 等于 4,表示 4 个队伍。单循环赛的赛程如下。【P106】

[算法课]算法考试复习范围全解_i++_03

#include<iostream>

using namespace std;

const int N = 100+10;
int map[N][N];
int k;

int plan(int KNum){
    //倍数初始化
    int n = 2;
    
    //左上角初始化
    map[1][1]=map[2][2]=1;
    map[1][2]=map[2][1]=2;
    
    for(int i=1;i<KNum;i++){
        //倍数控制
        int tmpN=n;
        n*=2;
        
        //右上角 等于左下+tmpN
        for(int i=tmpN+1;i<=n;i++)
            for(int j=1;j<=tmpN;j++)
                map[i][j]=map[i-tmpN][j]+tmpN;
        
        //左下角 等于右上
        for(int i=1;i<=tmpN;i++)
            for(int j=tmpN+1;j<=n;j++)
                map[i][j]=map[i+tmpN][j-tmpN];
        
        //右下角 等于左上
        for(int i=tmpN+1;i<=n;i++)
            for(int j=tmpN+1;j<=n;j++)
                map[i][j]=map[i-tmpN][j-tmpN];
    }
}
int main(){
    //倍数控制
    cin>>k;

    int n = 1<<k;
    
    plan(k);

    for(int i=1;i<=n;i++){   
        for(int j=1;j<=n;j++)
            cout<<map[i][j]<<" "; 
        cout<<endl;
    }
    return 0;
}

(3)蛮力法

① 选择法排序【注意是蛮力法的书写】【P125】

#include<iostream>
#include<vector>

using namespace std;

int n;
vector<int> a;

void SelectSort(vector<int> arr){
    for(int i=0;i<arr.size()-1;i++)
    {
        int lastNumIndex=i;
        for(int j=i+1;j<arr.size();j++)
            if(a[j]<=a[lastNumIndex])lastNumIndex = j;
        
        swap(a[lastNumIndex],a[i]);
    }
}

int main(){
    cin>>n;
    
    while(n--){int TmpN;cin>>TmpN;a.push_back(TmpN);}
    
    SelectSort(a);
    
    for(int x:a)cout<<x<<" ";
    
    return 0;
}
500 277
    218 97 78 13 7 259 14 90 86 460 72 134 458 2 245 490 126 33 355 171 166 433 16 74 436 167 5 296 350 148 146 279 230 467
    182 31 315 77 151 442 253 224 156 325 379 183 30 47 129 124 441 497 314 193 390 463 80 362 461 280 383 185 415 179 174
    234 214 1 199 244 249 398 473 136 394 349 369 63 83 356 440 363 219 484 330 425 465 176 125 269 289 312 162 451 480
    100 342 418 243 177 149 10 422 42 478 338 141 367 346 271 221 283 114 443 216 145 235 220 380 204 147 24 307 285 403
    175 256 477 305 165 416 420 255 227 211 427 370 223 195 9 69 264 35 17 38 384 56 329 300 246 178 203 39 471 55 46 
    103 263 455 231 487 445 188 268 482 58 294 257 449 391 500 392 479 261 492 96 267 88 116 494 206 43 262 71 180 120 
    142 351 29 340 130 310 57 431 226 276 6 437 187 447 270 345 66 374 210 133 348 215 242 419 469 435 37 331 84 59 28 
    117 430 426 488 222 399 452 448 273 158 150 170 40 110 217 229 232 76 303 382 241 275 108 366 409 499 26 311 302 
    486 91 347 334 94 358 491 196 107 360 401 292 191 4 297 475 378 298 236 389 22 359 233 163 212 92 53 288 472 476 
    327 153 278 99 483 115 143 407 205 344 498 316 132 8 190 181 113 160 317 410 48 60 105 127 239 250 400 70 213 377 
    154 474 319 322 495 44 397 62 313 411 393 164 496 111 51 291 429 172 470 168 54 157 225 208 20 328 417 106 324 135 
    489 240 326 64 265 404 450 318 98 444 237 308 104 352 155 438 396 152 293 25 371 68 408 432 112 301 73 11 128 354 
    251 254 87 434 247 34 332 252 192 258 323 412 341 12 385 45 65 228 357 466 281 49 194 284 137 406 372 485 454 123 
    36 169 209 41 140 353 299 375 402 320 121 459 457 138 75 421 144 274 339 93 207 197 82 61 200 287 364 102 266 50 
    260 343 373 81 456 198 202 173 388 85 282 23 290 386 333 446 424 189 462 95 468 286 335 361 295 321 368 186 413 101
    67 131 89 79 439 481 122 118 387 139 27 18 395 52 423 405 381 336 184 414 3 428 119 309 493 453 161 306 15 464 248 
    109 21 365 376 32 19 272 201 238 159 337 304 277

输出

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 
22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 
40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 
58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 
76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 
94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 
109 110 111 112 113 114 115 116 117 118 119 120 121 
122 123 124 125 126 127 128 129 130 131 132 133 134 
135 136 137 138 139 140 141 142 143 144 145 146 147 
148 149 150 151 152 153 154 155 156 157 158 159 160 
161 162 163 164 165 166 167 168 169 170 171 172 173 
174 175 176 177 178 179 180 181 182 183 184 185 186 
187 188 189 190 191 192 193 194 195 196 197 198 199 
200 201 202 203 204 205 206 207 208 209 210 211 212 
213 214 215 216 217 218 219 220 221 222 223 224 225 
226 227 228 229 230 231 232 233 234 235 236 237 238 
239 240 241 242 243 244 245 246 247 248 249 250 251 
252 253 254 255 256 257 258 259 260 261 262 263 264 
265 266 267 268 269 270 271 272 273 274 275 276 277 
278 279 280 281 282 283 284 285 286 287 288 289 290 
291 292 293 294 295 296 297 298 299 300 301 302 303 
304 305 306 307 308 309 310 311 312 313 314 315 316 
317 318 319 320 321 322 323 324 325 326 327 328 329 
330 331 332 333 334 335 336 337 338 339 340 341 342 
343 344 345 346 347 348 349 350 351 352 353 354 355 
356 357 358 359 360 361 362 363 364 365 366 367 368 
369 370 371 372 373 374 375 376 377 378 379 380 381 
382 383 384 385 386 387 388 389 390 391 392 393 394 
395 396 397 398 399 400 401 402 403 404 405 406 407 
408 409 410 411 412 413 414 415 416 417 418 419 420 
421 422 423 424 425 426 427 428 429 430 431 432 433 
434 435 436 437 438 439 440 441 442 443 444 445 446 
447 448 449 450 451 452 453 454 455 456 457 458 459 
460 461 462 463 464 465 466 467 468 469 470 471 472 
473 474 475 476 477 478 479 480 481 482 483 484 485 
486 487 488 489 490 491 492 493 494 495 496 497 498 
499 500

② 冒泡法排序【注意是蛮力法的书写】【P127】

书上写的莫名其妙
我这多方便

#include<iostream>
#include<vector>

using namespace std;

int n;
vector<int> a;

void BubbleSort(vector<int> arr){
    for(int i=0;i<arr.size();i++)
        for(int j=i+1;j<arr.size();j++)
            if(a[i]>a[j])swap(a[i],a[j]);
            
    return ;
}
int main(){
    cin>>n;
    
    int tmpN;
    for(int i=0;i<n;i++)cin>>tmpN,a.push_back(tmpN);
    
    BubbleSort(a);
    
    for(auto x:a)cout<<x<<" ";
    
    return 0;
}

测试数据

输入

500 277
    218 97 78 13 7 259 14 90 86 460 72 134 458 2 245 490 126 33 355 171 166 433 16 74 436 167 5 296 350 148 146 279 230 467
    182 31 315 77 151 442 253 224 156 325 379 183 30 47 129 124 441 497 314 193 390 463 80 362 461 280 383 185 415 179 174
    234 214 1 199 244 249 398 473 136 394 349 369 63 83 356 440 363 219 484 330 425 465 176 125 269 289 312 162 451 480
    100 342 418 243 177 149 10 422 42 478 338 141 367 346 271 221 283 114 443 216 145 235 220 380 204 147 24 307 285 403
    175 256 477 305 165 416 420 255 227 211 427 370 223 195 9 69 264 35 17 38 384 56 329 300 246 178 203 39 471 55 46 
    103 263 455 231 487 445 188 268 482 58 294 257 449 391 500 392 479 261 492 96 267 88 116 494 206 43 262 71 180 120 
    142 351 29 340 130 310 57 431 226 276 6 437 187 447 270 345 66 374 210 133 348 215 242 419 469 435 37 331 84 59 28 
    117 430 426 488 222 399 452 448 273 158 150 170 40 110 217 229 232 76 303 382 241 275 108 366 409 499 26 311 302 
    486 91 347 334 94 358 491 196 107 360 401 292 191 4 297 475 378 298 236 389 22 359 233 163 212 92 53 288 472 476 
    327 153 278 99 483 115 143 407 205 344 498 316 132 8 190 181 113 160 317 410 48 60 105 127 239 250 400 70 213 377 
    154 474 319 322 495 44 397 62 313 411 393 164 496 111 51 291 429 172 470 168 54 157 225 208 20 328 417 106 324 135 
    489 240 326 64 265 404 450 318 98 444 237 308 104 352 155 438 396 152 293 25 371 68 408 432 112 301 73 11 128 354 
    251 254 87 434 247 34 332 252 192 258 323 412 341 12 385 45 65 228 357 466 281 49 194 284 137 406 372 485 454 123 
    36 169 209 41 140 353 299 375 402 320 121 459 457 138 75 421 144 274 339 93 207 197 82 61 200 287 364 102 266 50 
    260 343 373 81 456 198 202 173 388 85 282 23 290 386 333 446 424 189 462 95 468 286 335 361 295 321 368 186 413 101
    67 131 89 79 439 481 122 118 387 139 27 18 395 52 423 405 381 336 184 414 3 428 119 309 493 453 161 306 15 464 248 
    109 21 365 376 32 19 272 201 238 159 337 304 277

输出

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 
22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 
40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 
58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 
76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 
94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 
109 110 111 112 113 114 115 116 117 118 119 120 121 
122 123 124 125 126 127 128 129 130 131 132 133 134 
135 136 137 138 139 140 141 142 143 144 145 146 147 
148 149 150 151 152 153 154 155 156 157 158 159 160 
161 162 163 164 165 166 167 168 169 170 171 172 173 
174 175 176 177 178 179 180 181 182 183 184 185 186 
187 188 189 190 191 192 193 194 195 196 197 198 199 
200 201 202 203 204 205 206 207 208 209 210 211 212 
213 214 215 216 217 218 219 220 221 222 223 224 225 
226 227 228 229 230 231 232 233 234 235 236 237 238 
239 240 241 242 243 244 245 246 247 248 249 250 251 
252 253 254 255 256 257 258 259 260 261 262 263 264 
265 266 267 268 269 270 271 272 273 274 275 276 277 
278 279 280 281 282 283 284 285 286 287 288 289 290 
291 292 293 294 295 296 297 298 299 300 301 302 303 
304 305 306 307 308 309 310 311 312 313 314 315 316 
317 318 319 320 321 322 323 324 325 326 327 328 329 
330 331 332 333 334 335 336 337 338 339 340 341 342 
343 344 345 346 347 348 349 350 351 352 353 354 355 
356 357 358 359 360 361 362 363 364 365 366 367 368 
369 370 371 372 373 374 375 376 377 378 379 380 381 
382 383 384 385 386 387 388 389 390 391 392 393 394 
395 396 397 398 399 400 401 402 403 404 405 406 407 
408 409 410 411 412 413 414 415 416 417 418 419 420 
421 422 423 424 425 426 427 428 429 430 431 432 433 
434 435 436 437 438 439 440 441 442 443 444 445 446 
447 448 449 450 451 452 453 454 455 456 457 458 459 
460 461 462 463 464 465 466 467 468 469 470 471 472 
473 474 475 476 477 478 479 480 481 482 483 484 485 
486 487 488 489 490 491 492 493 494 495 496 497 498 
499 500

③ 最大值连续子序问题【P129】

蛮力法做法

#include<iostream>
#include<vector>

using namespace std;

vector<int> arr;

int main(){
    int n;
    cin>>n;
        
    int tmpN;
    for(int i=0;i<n;i++)cin>>tmpN,arr.push_back(tmpN);
    
    auto  LS = []() ->int{
        int maxSum=0;
        for(int i=0;i<arr.size();i++)
            for(int j=i;j<arr.size();j++){
                int tmpSum=0;
                for(int p=i;p<=j;p++)tmpSum+=arr[p];
                maxSum = max(tmpSum,maxSum);
            }
        return maxSum;
    };
    
    cout<<LS();
    
    return 0;
}

[算法课]算法考试复习范围全解_ci_04

[算法课]算法考试复习范围全解_ci_05

④ 背包问题:【此题要求掌握纯蛮力法书写和深度优先算法书写】【P135 页】

有 n 个重量分别是 w1,w2…,wn 的物品(物品编号为 1-n)
它们的价值分别为 v1,v2,…,vn
给定一个容量为 W 的背包。设计从这些物品中选取一部分放入该背包的方案。
每个物品要么选中要么不选中【其实每个物品只有 1 件】,
要求选中的物品不仅能够放在背包中,而且具有最大的价值。
并对如下所展示的 5 个物品求出 W=10 时的最佳解。
物品编号 重量 价值
1 2 6 2 2 3 3 6 5 4 5 4 5 4 6

方法一:字符串蛮力

#include<iostream>
#include<cstring>
#include<algorithm>

using namespace std;

int main()
{
	int W = 10, n = 5;
	int w[5] = { 2,2,6,5,4 }, v[5] = { 6,3,5,4,6 };

	string pres = "00000";

	int ww = 0, vv = 0, maxv = 0;
	string str;
	char s[1000];

	for (int j = 0; j < 5; j++)
		for (int a = 0; a < 5; a++)
			for (int b = 0; b < 5; b++)
				for (int c = 0; c < 5; c++)
					for (int d = 0; d < 5; d++)
						for (int e = 0; e < 5; e++)
						{
							if (a != b && a != c && a != d && a != e);
							if (b != c && b != d && b != e);
							if (c != d && c != e);
							if (d != e);

							pres[j]='1';

							s[0] = pres[a]; 
							s[1] = pres[b]; 
							s[2] = pres[c]; 
							s[3] = pres[d]; 
							s[4] = pres[e];

							//cout << s[0] << " " << s[1] << " " << s[2] << " " << s[3] << " " << s[4] << " " << endl;
							for (int i = 0; i < 5; i++)ww += (s[i] - '0')*w[i], vv += (s[i] - '0')*v[i];

							//当前背包重量不超过容量,且vv当前背包价值大于最大价值
							if (ww <= W && vv > maxv)maxv = vv, str = s;//记录此时的s的组合

							vv = 0, ww = 0;
						}
	for (int i = 0; i < 5; i++)cout << str[i];
	cout << endl;
	cout << maxv << endl;

	return 0;
}

方法二:二进制枚举蛮力

#include<iostream>

using namespace std;

int ww,vv,maxv,strres;

int main()
{
	int W = 10;
	int w[5] = { 2,2,6,5,4 }, v[5] = { 6,3,5,4,6 };

	for(int i=0;i<1<<5;i++)//二进制最大可能选择数
	{
        for(int j=0;j<5;j++)ww += (i>>j&1)*w[j], vv += (i>>j&1)*v[j];/判断当前位子是否被选择,更新0或1倍目标值的数值
				
		if (ww <= W && vv > maxv)maxv = vv,strres=i;//更新

		vv = 0, ww = 0;
	}

    for(int i=0;i<5;i++)cout<<(strres>>i&1);//因为是选择情况,所以直接输出
    cout<<endl;
    
	cout << maxv;

	return 0;
}

方法三:DFS
无法保存最大路径

#include<iostream>

using namespace std;

int ww,vv,maxv,strres;
int W = 10;
int w[5] = { 2,2,6,5,4 }, v[5] = { 6,3,5,4,6 };
	
int str[5];
int ans[5];

void dfs(int tw,int ans)
{
    if(tw<=W&&ans > maxv){maxv = ans;return ;}
    
    for(int i=0;i<5;i++)
        if(!str[i]&&tw>=w[i])
        {
            str[i]=1;
            dfs(tw-w[i],ans+v[i]);
            str[i]=0;
        }
    
}
int main()
{
    dfs(W,0);
    
	cout << maxv;

	return 0;
}

方法四 颜老师角度

#include<iostream>

using namespace std;

int w[5] = { 2,2,6,5,4 }, v[5] = { 6,3,5,4,6 };

int x[5];
int maxv = 0;
int ans[5];

void dfs(int i, int ww, int vv)
{
	if (i == 5)
		if (ww <= 10 && vv > maxv) { maxv = vv; for(int i=0;i<5;i++)ans[i]=x[i];return; }//记录最优状态
	    else return;//这里给他加了个退出
	    
	x[i] = 1;
	dfs(i + 1, ww + w[i], vv + v[i]);
	x[i]=0;
	dfs(i + 1, ww, vv);
}

int main()
{

	dfs(0, 0, 0);

	for(auto x:ans)cout<<x;
	cout<<endl;
	
	cout << maxv;

	return 0;
}

(4)回朔法

① 设计一个算法在 1,2,……9(顺序不变)【P172 页】

数值之间插入+或者-或者什么都不插入,
使得计算结果总是 100 的程序。
例如 1+2+34-5+67-8+9=100。
输出所有的答案。

DFS 暴力搜索

#include<iostream>

using namespace std;

const int N=9;
int arr[N]={1,2,3,4,5,6,7,8,9};
char op[N];	//最多有九个符号

void func(int sum,int preAdd,int i){	//sum 总数 preAdd上一个添加的数字 i记录当前是第几个
        if(i==N){//选完前9个数字
            if(sum==100){//总数到100
                cout<<arr[0];//输出第一个数字
                for(int j=1;j<N;j++){
                    if(op[j]!=' ')cout<<op[j];//如果当前符号不是空格,就输出符号
                    cout<<arr[j];//输出数字
                }
                cout<<"=100"<<endl;
            }
            return ;
        }
        else {
            op[i]='+';//符号是+的情况
            func(sum+arr[i],arr[i],i+1);//记录状态
              
            op[i]='-';//符号是-的情况
            func(sum-arr[i],-arr[i],i+1);
            
            op[i]=' ';//符号是空格的状态
            int tmpN=0;//计算当前数字与前一个数字和一的新数字
            if(preAdd>0)tmpN=preAdd*10+arr[i];//如果前一个数字是正数 那么新的合就是正数
            else tmpN=preAdd*10-arr[i];
            func(sum-preAdd+tmpN,tmpN,i+1);//记录新状态 总数-上一个数字+新融合的数字 preAdd是新数字 i+1去选择下一个数字
        }
    }
    
int main(){
    
    func(arr[0],arr[0],1);//起始
    
    return 0;
}

[算法课]算法考试复习范围全解_i++_06

② 0 和 1 背包问题【使用回朔法解决】【P178 页】

#include<iostream>

using namespace std;

const int N=1e3+10;

int v[N],w[N];

int n,m;
int maxV;

bool tmpAns[N],Ans[N];

void dfs(int u,int tv,int tw){
    if(u>n){
        if(tv>maxV&&tw==m){
            maxV = tv;
            for(int i=1;i<=n;i++)Ans[i]=tmpAns[i];
        }
    }
    else {
        tmpAns[u]=true;
        dfs(u+1,tv+v[u],tw+w[u]);
        tmpAns[u]=false;
        
        dfs(u+1,tv,tw);
    }
    
    return ;
}

int main(){
    // n 数量 m是最大重量限制
    cin>>n>>m;
    
    for(int i=1;i<=n;i++)cin>>w[i];
    for(int i=1;i<=n;i++)cin>>v[i];
    
    dfs(1,0,0);
    
    for(int i=1;i<=N;i++)if(Ans[i])cout<<i<<" ";
    
    int sumV=0;
    for(int i=1;i<=N;i++)if(Ans[i])sumV+=v[i];
    
    int sumW=0;
    for(int i=1;i<=N;i++)if(Ans[i])sumW+=w[i];
    
    cout<<sumV<<" "<<sumW<<endl;
    
    return 0;
}

[算法课]算法考试复习范围全解_i++_07

③ 活动安排问题【P198 页】

#include<iostream>
#include<algorithm>
#include<vector>

using namespace std;

typedef pair<int,int> PII;
vector<PII>PIIArr;

int n;
const int N=100+10;
int AnsArr[N];

void slove(){
    sort(PIIArr.begin(),PIIArr.end(),[&](PII a,PII b){return a.second<b.second;});
    
    int preEnd=0;
    for(int i=0;i<PIIArr.size();i++){
        if(PIIArr[i].first>=preEnd){
            AnsArr[i]=1;
            preEnd = PIIArr[i].second;
        }
    }
    return ;
}
int main(){
    cin>>n;
    
    int tmpN_A,tmpN_B;
    while(n--)cin>>tmpN_A>>tmpN_B,PIIArr.push_back({tmpN_A,tmpN_B});
    
    slove();
    
    int sumN=0;
    for(int i=0;i<N;i++)if(AnsArr[i]==1){sumN++;cout<<i+1<<" ";}
    
    cout<<endl<<sumN;
    
    return 0;
}

输入输出

[算法课]算法考试复习范围全解_数组_08

④ 迷宫问题 【P154 页】

有如下 8*8 的迷宫


O X X X X X X X O O O O O X X X X O X X O O O X X O X X O X X O X O X X X X X X X O X X O O O X X O O O O X O O X X X X X X X O


其中,O 表示通路方块,X 表示障碍方块。
假设入口位置是(0,0),出口位置为右下角方块位置是(7,7)。
设计一个程序求指定入口到出口的一条迷宫路径。

方便获取的数据

"OXXXXXXX",
"OOOOOXXX",
"XOXXOOOX",
"XOXXOXXO",
"XOXXXXXX",
"XOXXOOOX",
"XOOOOXOO",
"XXXXXXXO"

答案

XXXXXXX
  OOOXXX
X XXOOOX
X XXOXXO
X XXXXXX
X XX   X
X    X  
XXXXXXXO

完整代码

#include<iostream>
#include<string.h>

using namespace std;

const int max = 8+2;
string map[] = {
"OXXXXXXX",
"OOOOOXXX",
"XOXXOOOX",
"XOXXOXXO",
"XOXXXXXX",
"XOXXOOOX",
"XOOOOXOO",
"XXXXXXXO"
};
int beginX=0,beginY=0;
int endX=7,endY=7;

int dx[]={-1,0,1,0},dy[]={0,1,0,-1};

void dfs(int x,int y){
    if(x==endX&&y==endY){
        for(int i=0;i<sizeof(map)/map[0].length();i++)
            {
            for(int j=0;j<map[0].length();j++)
                cout<<map[i][j];
            cout<<endl;
            }
    }
    else {
        for(int i=0;i<4;i++){
            if((unsigned int)x<(int)(sizeof(map)/map[0].length())
            &&(unsigned int)y<(int)(map[0].length())
            &&map[x][y]=='O'){
                map[x][y]=' ';
                dfs(x+dx[i],y+dy[i]);
                map[x][y]='O';
            }
        }
    }
}

int main(){
    
    dfs(beginX,beginY);

      
    return 0;
}

(5)贪心法

① 顾客在超市购买物品一共消费 x 元【任意输入 x 的值,x 的值在 1 到 100 之间,、并且是整数】。支付的纸币为 100 元,计算超市收银员应找回顾客多少钱?【告知前提所有的纸币数量充足下,纸币包含面额是 100 元、50 元、20 元、5 元、1 元】

思路
优先大的原则
代码

解法1.贪心

#include<iostream>
#include<vector>
#include<algorithm>

using namespace std;

bool cmp(int a,int b){return a>b;}
int main()
{
    vector<int>a;
    int sumPrice,n;
    cin>>sumPrice>>n;
    for(int i=0;i<n;i++){int t;cin>>t;a.push_back(t);}
    
    sort(a.begin(),a.end(),cmp);
    
    int res=0;
    for(int i=0;i<n;i++)
        res+=(sumPrice/a[i]),sumPrice%=a[i];
    
    cout<<res;
    
    return 0;
}

测试数据

431 7 100 1 2 5 10 20 50

② 柠檬水找零

在柠檬水摊上,每一杯柠檬水的售价为 5 美元。
顾客排队购买你的产品,(按账单 bills 支付的顺序)一次购买一杯。
每位顾客只买一杯柠檬水,然后向你付 5 美元、10 美元或 20 美元。
你必须给每个顾客正确找零,也就是说净交易是每位顾客向你支付 5 美元。
注意,一开始你手头没有任何零钱。
如果你能给每位顾客正确找零,返回 true ,否则返回 false 。
示例 1:
输入:[5,5,5,10,20]
输出:true

[算法课]算法考试复习范围全解_数组_09


代码

解法1.模拟

class Solution {
public:
    int cnt5,cnt10,cnt20;
    bool lemonadeChange(vector<int>& bills) {
        int f=true;
        for(int x:bills)
            if(x==5)cnt5++;
            else if(x==10&&cnt5)cnt10++,cnt5--;
            else if(x==20&&cnt10&&cnt5)cnt20++,cnt10--,cnt5--;
            else if(x==20&&cnt5>=3)cnt20++,cnt5-=3;
            else {f=false;break;}
        return f;
    }
};

解法2. 贪心
我们拿 321 来举例
这个时候 a1>a2>a3
我们可以直观察觉,直到299为止都不会有正确数据
于是我们粗略的得到 ai>ai+1时,a[0]-=1,a[i]->a[asize]=9

但是此时显然不符合231 这样的数据,因为显然只需要 229即可,所以现在的设想是 a[i]-=1,a[i+1]->a[a.size]=9

以 332来举例 我们简化为 329时,又发现不满足ai>ai+1的情况
于是我们需要把i从头再排查一遍,直接i=-1

class Solution {
public:
    vector<int>a;
    
    int monotoneIncreasingDigits(int N) {
        if(N<10)return N;

        while(N)
        {
            a.push_back(N%10);
            N/=10;
        }

        reverse(a.begin(),a.end());

        for(int i=0;i<a.size()-1;i++)
            {
                if(a[i]>a[i+1])
                    {
                        a[i]--;
                        for(int j=i+1;j<a.size();j++)a[j]=9;
                        i=-1;//感觉简直神来之笔,本来我用递归,差点没自闭
                    }
            }

        for(int i=0;i<a.size();i++)cout<<a[i]<<endl;

        int res=0;
        for(int i=0;i<a.size();i++)res=res*10+a[i];
        return res;
    }
};

③ 简单背包问题【P251 页】

这是一道完全背包问题

我们只需要理解,price/weight==val
如果val越高,就越优先处理即可
那么我们最终只需要一个结构体排序即可

代码

解法1.结构体排序

#include<iostream>
#include<algorithm>

using namespace std;

struct Node{
    string name;
    int price,weight;
};

bool cmp(Node a,Node b){return a.price/a.weight>b.price/b.weight;}//自定义结构体sort降序

int main()
{
    int sum,n;
    cin>>sum>>n;
    
    const int len = n;
    Node node[len+10];
    
    for(int i=0;i<len;i++)
        cin>>node[i].name>>node[i].weight>>node[i].price;
    
    sort(node,node+len,cmp);
    
    int cnt=0;
    while(sum)
    {
        if(sum>=node[cnt].weight){cout<<node[cnt].name<<" "<<node[cnt].weight<<endl;sum-=node[cnt].weight;}//优先处理最高
        else
        {
            cout<<node[cnt].name<<" "<<sum<<endl;
            sum=0;
        }
        cnt++;
    }   
    return 0;
}

待改

#include<iostream>
#include<vector>
#include<algorithm>

using namespace std;

typedef pair<int,int> PII;

int main(){
    int tn;
    double tmaxW;
    cin>>tn>>tmaxW;
    
    auto func = [](int n,int maxW){
        vector<PII>ansArr;
        
        double tmpv,tmpw;
        for(int i=0;i<n;i++)cin>>tmpv>>tmpw,ansArr.push_back((PII){tmpv,tmpw});
    
        sort(ansArr.begin(),ansArr.end(),[](PII a,PII b){
            return (double)a.first/a.second > (double)b.first/b.second;
        });
        
        int ansV=0;
        for(int i=0;i<n;i++)
            if(maxW>=ansArr[i].second){
                //std::cout<<ansArr[i].first<<" "<<ansArr[i].second<<" "<<(double)ansArr[i].first/(double)ansArr[i].second <<endl;
                ansV+=ansArr[i].first;
                maxW-=ansArr[i].second;
            }
            else {
                //std::cout<<ansArr[i].first<<" "<<ansArr[i].second<<" "<<(double)ansArr[i].first/(double)ansArr[i].second <<endl;
                ansV+=(double)ansArr[i].first/(double)ansArr[i].second*maxW;
                break;
            }
        
        return ansV;
    };
    
    cout<<func(tn,tmaxW);
    
    return 0;
}

[算法课]算法考试复习范围全解_数组_10

④ 求解活动安排问题【P246】

#include<iostream>
#include<algorithm>
#include<vector>

using namespace std;

typedef pair<int,int> PII;
vector<PII>PIIArr;

int n;
const int N=100+10;
int AnsArr[N];

void slove(){
    sort(PIIArr.begin(),PIIArr.end(),[&](PII a,PII b){return a.second<b.second;});
    
    int preEnd=0;
    for(int i=0;i<PIIArr.size();i++){
        if(PIIArr[i].first>=preEnd){
            AnsArr[i]=1;
            preEnd = PIIArr[i].second;
        }
    }
    return ;
}
int main(){
    cin>>n;
    
    int tmpN_A,tmpN_B;
    while(n--)cin>>tmpN_A>>tmpN_B,PIIArr.push_back({tmpN_A,tmpN_B});
    
    slove();
    
    int sumN=0;
    for(int i=0;i<N;i++)if(AnsArr[i]==1){sumN++;cout<<i+1<<" ";}
    
    cout<<endl<<sumN;
    
    return 0;
}

[算法课]算法考试复习范围全解_数组_11

(6)动态规划

① 使用动态规划发,求 fibonacci 数列。【P282】

#include<iostream>

using namespace std;

const int MAXLen = 100+10;

int map[MAXLen]={0,1,1};

int fib(int n){
    for(int i=3;i<=n;i++)map[i]=map[i-1]+map[i-2];
    return map[n];
}

int main(){
    int n;
    cin>>n;
    
    cout<<fib(n);
    
    return 0;
}

② 求解整数拆分问题。【P291】

数据N尽量拆分!
最大不超过K

1.初始化
2.K>N 答案与f(K,N)相同
3.K=N 答案是F(K,N-1)+1 等于上一个答案拆分出来一个
4.k<N 答案是F(i-j,j)/包含J的情况/ +F(i,j-1)/所有数据都小于J的情况/

#include<iostream>

using namespace std;

int n,k;

const int N=110;
int dp[N][N];

int getAns(int n,int k){
    for(int i=1;i<=n;i++)
        for(int j=1;j<=k;j++)
            if(i==1||j==1)dp[i][j]=1;
            else if(i<j)dp[i][j]=dp[i][i];
            else if(i==j)dp[i][j]=dp[i][j-1]+1;
            else if(i>j)dp[i][j]=dp[i-j][j]+dp[i][j-1];
                
    return dp[n][k];
}
int main(){
    cin>>n>>k;
    
    cout<<getAns(n,k);
    
    return 0;
}

方法二

1.需要拆分的数据必然比拆分的数据更大 所以J>=I
2.可拆分的数据等于所有拆分掉自身可拆分数据的数据价值的累加

#include<iostream>
#include<vector>

using namespace std;

int tn,tk;

int main(){
    cin>>tn>>tk;
    
    auto func = [](int n,int k) -> int {
        vector<int> a(n+1,0);
        a[0]=1;//初始化
        
        for(int i=1;i<=tk;i++)  	//可能拆分的值
            for(int j=i;j<=tn;j++)	//被拆分数据
                a[j]+=a[j-i];
        
        return a[tn];
    };
    
    cout<<func(tn,tk);
    
    return 0;
}

[算法课]算法考试复习范围全解_数组_12

③ 求解 0/1 背包问题【P307】

有 N 件物品和一个容量是 V 的背包。每件物品只能使用一次。

第 i 件物品的体积是 vi,价值是 wi。

求解将哪些物品装入背包,可使这些物品的总体积不超过背包容量,且总价值最大。
输出最大价值。

输入格式
第一行两个整数,N,V,用空格隔开,分别表示物品数量和背包容积。

接下来有 N 行,每行两个整数 vi,wi,用空格隔开,分别表示第 i 件物品的体积和价值。

输出格式
输出一个整数,表示最大价值。

#include<iostream>

using namespace std;

const int N=1000+10;
int dp[N][N],w[N],v[N];

int n,m;

int main(){
    cin>>n>>m;
    
    for(int i=1;i<=n;i++)cin>>v[i]>>w[i];
    
    for(int i=1;i<=n;i++)
        for(int j=1;j<=m;j++)
            if(j>=v[i])dp[i][j]=max(dp[i-1][j-v[i]]+w[i],dp[i-1][j]);
            else dp[i][j]=dp[i-1][j];
    
    int res=-0x3f3f3f;
    for(int i=0;i<=m;i++)res=max(res,dp[n][i]);
    cout<<res;
    
    return 0;
}

④ 最长公共子序列【P299】

下表来自https://leetcode-cn.com/problems/longest-common-subsequence/solution/dong-tai-gui-hua-zhi-zui-chang-gong-gong-zi-xu-lie/

[算法课]算法考试复习范围全解_i++_13


这里表示的概念是

两个字符串相互比较

f[i][j]就表明str1前i个和str2前j个比对,LCS的最大数量

我们只依据两个原则
1.如果str1[i-1]==str1[j-1] 那么你的LCS数量就是前面两个字符 dp[i-1][j-1]+1
2.如果1不成立,那么当前位子的LCS数量 dp[i-1][j]或者dp[i][j-1]的最长的一个

这样概念就相对清晰

如果还不明白 别人珠玉在前 我就不写了
https://leetcode-cn.com/problems/longest-common-subsequence/solution/dong-tai-gui-hua-zhi-zui-chang-gong-gong-zi-xu-lie/

#include<iostream>
#include<algorithm>
#include<vector>
#include<string>

using namespace std;

string str1,str2;

int main(){
    cin>>str1>>str2;
    
    auto LCS = [](string str1,string str2)->int {
        
    int strLen1=str1.size(),strLen2=str2.size();
    
    vector<vector<int>>dp(strLen1+1,vector<int>(strLen2+1,0));//生成str1+1长str2+1宽的DPTable 全部赋值为0    
    
    for(int i=1;i<=strLen1;i++)
        for(int j=1;j<=strLen2;j++)
            if(str1[i-1]==str1[j-1])dp[i][j]=dp[i-1][j-1]+1;//如果相等就证明是新的LCS+1
            else dp[i][j]=max(dp[i-1][j],dp[i][j-1]);//如果不相等就证明起码有一个不在LCS里,取dp[i-1][j]dp[i][j-1]最大
            
    return dp[strLen1][strLen2];
    };
    
    cout<<LCS(str1,str2);
    
    return 0;
}

[算法课]算法考试复习范围全解_i++_14