输油管道
分治–棋盘覆盖问题
详解PPT:https://wenku.baidu.com/view/e331f06c336c1eb91a375d75.html
详解博客:https://blog.csdn.net/sunshine__0411/article/details/78413823
#include<iostream>
using namespace std;
int tile=1;
int board[101][101]={0};
void chessBoard(int tr,int tc,int dr,int dc,int size)
{
//tr、tc:棋盘左上角行号、列号
//dr、dc:特殊方格所在行号
//size:2^k,棋盘规格=2^k * 2^k
if(size==1)
return;
int t=tile++;
int s=size/2;
/*
左上棋盘(dr<tr+s&&dc<tc+s)的右下角方格board[tr+s-1][tc+s-1]
右上棋盘(dr<tr+s&&dc>=tc+s)的左下角方格board[tr+s-1][tc+s]
右下棋盘(dr>=tr+s&&dc>=tc+s)的左上角方格board[tr+s][tc+s]
左下棋盘(dr>=tr+s&&dc<tc+s)的右上角方格board[tr+s][tc+s-1]
*/
//左上角子棋盘,
if(dr<tr+s&&dc<tc+s)
{ //特殊方格在继续分,s=size/2
chessBoard(tr,tc,dr,dc,s);
}
else
{ //无特殊方格
board[tr+s-1][tc+s-1]=t;//覆盖子棋盘右下角的一个方格
chessBoard(tr,tc,tr+s-1,tc+s-1,s);//覆盖该子棋盘的其余方格
}
//右上角子棋盘
if(dr<tr+s&&dc>=tc+s)
{ //特殊方格在此棋盘中:右上角棋盘的列发生变化
chessBoard(tr,tc+s,dr,dc,s);
}
else
{ //此棋盘无特殊方格
board[tr+s-1][tc+s]=t;//覆盖该子棋盘的左下角一个方格
chessBoard(tr,tc+s,tr+s-1,tc+s,s);//覆盖该子棋盘的其余方格
}
//左下角子棋盘
if(dr>=tr+s&&dc<tc+s)
{
//特殊方格在此棋盘中
chessBoard(tr+s,tc,dr,dc,s);//对该子棋盘继续划分
}
else
{
//无特殊方格
board[tr+s][tc+s-1]=t;//对左下棋盘的右上角方格进行覆盖
chessBoard(tr+s,tc,tr+s,tc+s-1,s);
}
//右下角子棋盘
if(dr>=tr+s&&dc>=tc+s)
{
//特殊方格在此棋盘中
chessBoard(tr+s,tc+s,dr,dc,s);
}
else
{
//此棋盘无特殊方格
board[tr+s][tc+s]=t;//对右下角棋盘的左上角方格进行覆盖
chessBoard(tr+s,tc+s,tr+s,tc+s,s);
}
}
int main()
{
/*
0 0 12 14 16
1 2 4 举例理解极好
*/
int tr, tc, dr, dc, size;
cin>>dr>>dc>>size;
//chessBoard(0,0,12,14,16);
chessBoard(0, 0, dr, dc, size);
cout<<tile<<endl;
for(int i=0;i<size;i++){ //输出结果
for(int j=0;j<size;j++){
cout.width(5);
cout<<board[i][j];
if(j==size-1){
cout<<endl<<endl;
}
}
}
return 0;
}
01背包(可输出物品)
//背包问题
//配合这篇讲解
#include<iostream>
#include<algorithm>
#include<cstring>
using namespace std;
#define N 10//N件宝贝上限
#define C 50//C是背包的总capacity,上限
int n,c;
int main()
{
int i=1;
int j=1;
int value[N+1];//价值?
int weight[N+1];//重量?
int f[N+1][C+1];//f[i][j]表示在背包容量为j的情况下,前i件宝贝的最大价值
memset(value,0,sizeof(value));
memset(weight,0,sizeof(weight));
memset(f,0,sizeof(f));
cout<<"请输入宝贝个数、背包容量:"<<endl;
cin>>n>>c;
cout<<"依次输入宝贝重量、宝贝价值:"<<endl;
for(int i=1;i<=n;i++)
cin>>weight[i]>>value[i];
//外循环控制物品数量,确保每个物品都会被遍历到
for(int i=1;i<=n;i++)
{
/*for(j=weight[i];j<=C;j++) //内循环控制物品的重量,确保能够遍历出“以前每个物品放入时的最大价值f[i][j]”
{
intx=f[i-1][j]; //不放第i件物品
inty=f[i-1][j-weight[i]]+value[i]; //放入第i件物品
f[i][j]=max(x,y);
}*/
//内循环控制物品的重量,确保能够遍历出"以前每个物品放入时的最大价值f[i][j]"
for(j=1;j<=c;j++)
{
//背包容量为j时,遍历物品集合,选取价值最大的情况
//递推关系式
if(j<weight[i])
{
f[i][j]=f[i-1][j];
}
else
{
//放与不放,选取极大值
f[i][j]=max(f[i-1][j] , f[i-1][j-weight[i]]+value[i]);
}
}
}
//行=物品数量,列=背包容量
for(i=0;i<=n;i++)
{
for(j=0;j<=c;j++)
{
printf("%4d",f[i][j]);
}
cout<<endl;
}
cout<<endl<<"选取的最大价值是:"<<f[n][c]<<endl;
cout<<"选取的物品如下:"<<endl;
i=n,j=c;
//逆推
while(i)
{
if(f[i][j]==(f[i-1][j-weight[i]]+value[i]))
{
cout<<"物品:"<<i<<":"<<"weight="<<weight[i]<<",value="<<value[i]<<endl;
j-=weight[i];
}
i--;
}
cout<<endl;
return 0;
}
/*
3 10
3 4
4 5
5 6
*/
01背包
#include <iostream>
#include <cstdio>
#include <cstdlib>
using namespace std;
const int MAXN = 100;
int main()
{
int n, V;
int f[MAXN][MAXN];
int w[MAXN], p[MAXN];
//
cout<<"输入物品个数n、背包总容量V"<<endl;
while(cin>>n>>V)
{
cout<<" *****"<<endl;
if(n == 0 && V == 0)
break;
//初始化我的包包f、单个物品重量w、单个物品价值p
for(int i = 0; i <= n; ++i)
{
w[i] = 0, p[i] = 0;
for(int j = 0; j <= n; ++j)
{
f[i][j] = 0;
}
}
//注意以下循环都是从1开始的
//输入n个物品的单个物品重量w、单个物品价值p
cout<<"依次输入物品重量、物品价值,如:1 2"<<endl;
for(int i = 1; i <= n; ++i)
cin>>w[i]>>p[i];
//挨个遍历n个物品
for(int i = 1; i <= n; ++i)
{
int v = 1;
while(v < w[i])//判断每个物品选取与不选取的时候,都要从背包为空开始枚举
{
//背包容量依次增大
f[i][v] = f[i-1][v];
++v;
}
//当背包容量刚好可以容纳某个物品时,进行放与不放的选择
for(v = w[i]; v <= V; ++v)
//第i件物品的放与不放进行最大价值的比较
f[i][v] = max(f[i-1][v], f[i-1][v-w[i]]+p[i]);
}
cout<<f[n][V]<<endl;
}
return 0;
}
贪心背包
#include<cstdio>
#include <iostream>
#include<vector>
using namespace std;
int LEN; //定义全局变量
struct Element
{
float w;
float v;
float per;
int i;
};
void mergeSort(Element *d)
{
Element temp;
for(int i=0;i<LEN-1;++i)
{
for(int j=0;j<LEN-1-i;++j)
{
if(d[j].per<d[j+1].per)
{
temp=d[j];
d[j]=d[j+1];
d[j+1]=temp;
}
}
}
}
float knapsack(float c,vector <float> weight,vector <float> value,float *x)
{
int n=LEN;
Element d[LEN]={0};
int i;
for(i=0;i<n;++i)
{
cout<<weight.at(i)<<" "<<value.at(i)<<endl;
d[i].w=weight.at(i);
d[i].v=value.at(i);
d[i].per=value.at(i)/weight.at(i);
d[i].i=i;
}
mergeSort(d);
float opt=0;
for( i=0;i<n;++i)
x[i]=0;
for( i=0;i<n;++i)
{
if(d[i].w>c)
break;
x[d[i].i]=1;
opt+=d[i].v;
c-=d[i].w;
}
if(i<n)
{
x[d[i].i]=c/d[i].w;
opt+=x[d[i].i]*d[i].v;
}
return opt;
}
int main()
{
vector <float> weight;
vector <float> value;
// float w[LEN]={12.5,10,9,8,6,7,5,3,2.5,4.6};
// float v[LEN]={10,9,8,6,3,4,5,3,1.2,2.2};
float w,v=0;
int bag_capacity=0;
cout<<"请输入背包容量:";
cin>>bag_capacity;
cout<<"输入物品重量和价值,-1 -1退出!例如:15 12"<<endl;
// while(w!=-1){
// scanf("%f,%f",&w,&v);
// weight.push_back(w);
// value.push_back(v);
// }
float ws[10]={12.5,10,9,8,6,7,5,3,2.5,4.6};
float vs[10]={10,9,8,6,3,4,5,3,1.2,2.2};
for(int i=0;i<10;i++){
weight.push_back(ws[i]);
value.push_back(vs[i]);
}
LEN = weight.size();
// vector<float>::iterator it;
// for(it=weight.begin();it!=weight.end();it++)
// cout<<*it<<endl;
float choice[LEN]={0};
// float x[LEN]={0};
float opt=knapsack(bag_capacity,weight,value,choice);
// printf("opt:%f\n",opt);
// printf("x数组为:");
for(int i=0;i<LEN;++i)
{
if(choice[i]>0){
cout<<i<<"号"<<choice[i]<<"重量:"<<weight.at(i)*choice[i]<<"\t价值:"<<value.at(i)*choice[i]<<endl;
}
// printf("%f ",choice[i]);
}
putchar('\n');
system("pause");
return 0;
}
二分查找
快速排序
//https://blog.csdn.net/Pit3369/article/details/86301457,自己当时写的博客
import java.util.Scanner;
public class QuickSort {
public static int partition(int[] array,int lo,int hi) {
int pivot=array[lo];
while(lo<hi) {
while((lo<hi)&&(pivot<array[hi])) hi--;
if(lo<hi)
array[lo++]=array[hi];
while((lo<hi)&&(pivot>array[lo])) lo++;
if(lo<hi)
array[hi--]=array[lo];
}
array[lo]=pivot;
return lo;
}
public static void quickSort(int[] array,int low,int high) {
if(low<high) {
int m=partition(array,low,high);
quickSort(array,low,m-1);
quickSort(array, m+1, high);
}
}
public static void main(String[] args) {
Scanner in=new Scanner(System.in);
int num;
System.out.println("输入数组大小:");
num=in.nextInt();
int[] array=new int[num];
for (int i = 0; i < num; i++) {
int n=in.nextInt();
array[i]=n;
}
long time1 = System.currentTimeMillis();
quickSort(array,0,num-1);
long time2 = System.currentTimeMillis();
System.out.println("排序耗时:"+(time2-time1));
for (int i : array) {
System.out.print(i+" ");
}
}
}
走台阶
package chapter_1;
//走台阶
public class walk_the_steps {
public static int JumpFloor(int target) {
if(target==0)
return 0;
if(target==1)
return 1;
if(target==2)
return 2;
return JumpFloor(target-1)+JumpFloor(target-2);
}
public static int abnormal_JumpFloor(int target) {
//变态跳楼梯
//https://blog.csdn.net/Hackbuteer1/article/details/6686747
if(target==1)
return 1;
if(target==2)
return 2;
return 2*abnormal_JumpFloor(target-1);
}
public static void main(String[] args) {
int count=0;
int i,j,k;
int h=3;
for(i=0;i<=h;i++)
for(j=0;2*j<=h;j++)
if((i+2*j)==h) {
System.out.printf("i=%d,j=%d\n",i,j);
count++;
}
System.out.println("找到"+count+"种方法!");
System.out.println(JumpFloor(h));
}
}
汉诺塔问题
package chapter_1;
import java.util.ArrayList;
import java.util.Scanner;
//汉诺塔问题
public class Hanoi {
static int count=0;
public static void move(int n,char P,char Q) {
System.out.println("第"+(++count)+"次移动:把"+n+"号盘子从"+P+"--移动至-->"+Q);
}
public static void hanoi(int n,char A,char B,char C) {
if(n>0) {
hanoi(n-1,A,C,B);//递归,将A塔上1~n-1的圆盘移到B上,以C为辅助塔
move(n,A,C);
hanoi(n-1,B,A,C);//递归,把B塔上1~n-1的圆盘移到C上,以A为辅助塔
}
}
public static void main(String[] args) {
int disks;
char A='A';
char B='B';
char C='C';
Scanner in=new Scanner(System.in);
System.out.println("汉诺塔共有多少层?input n");
disks=in.nextInt();
hanoi(disks,A,B,C);
System.out.println("总共移动圆盘次数:"+count);
in.close();
}
}
整数划分问题
package chapter_1;
import java.util.Scanner;
/*
6;
5+1;
4+2,4+1+1;
3+3,3+2+1,3+1+1+1;
2+2+2,2+2+1+1,2+1+1+1+1;
1+1+1+1+1+1。
https://www.cnblogs.com/hoodlum1980/archive/2008/10/11/1308493.html
*/
public class Integer_division {
static int[] array=new int[200];
static int n=0;
static int integer_division(int n,int m) {
if(n==1||m==1)
return 1;
else if(n<m)
return integer_division(n,n);
else if(n==m)
return integer_division(n,m-1)+1;
else{
return integer_division(n,m-1)+integer_division(n-m,m);
}
}
public static void print(int sum,int index,int m) {
if(sum>n)
return ;
if(sum==n) {
for (int i = 0; i < index-1; i++)
System.out.print(array[i]+"+");
System.out.println(array[index-1]);
}
else {
for (int i = m; i >0; i--) {//注意此处for循环内:大至小 小至大 的区别。
array[index]=i;
sum+=i;
print(sum,index+1,i);
sum-=i;
}
}
}
public static void main(String[] args) {
int m;
System.out.println("请输入待划分数n、最大划分数m:");
Scanner in =new Scanner(System.in);
n=in.nextInt();
m=in.nextInt();
int count=integer_division(n,m);
System.out.println(count+"种划分结果!");
//划分总和sum、第index个划分数索引、最大划分数m
print(0,0,m);
}
}
统计数字问题
本着书本页码不会太大的小小懒惰思想,把页码定义为long类型。
package chapter_1;
import java.util.Arrays;
import java.util.Scanner;
//统计数字问题
/*
* 本书的页码从自然数1开始顺序编码直到自然数n.
* 书的页码按照通常的习惯编排,每个页码都不含多余的前导数字0.
* 例如,第6页用数字6表示,而不是06或006等.数字计数问题要求对给定书的总页码n,
* 计算出书的全部页码中分别用到多少次数字0,1,2,…,9.
*/
public class statistical_figures {
public static void main(String[] args) {
long num = 0;
Scanner in =new Scanner(System.in);
num=in.nextLong();
count_num(num);
System.out.println(num);
}
public static void count_num(long num) {
int[] nums = new int[10];
while(num!=0) {
nums[(int) (num%10)]++;
num=num/10;
}
//Arrays.sort(nums);
//System.out.println(Arrays.toString(nums));
for (int i = 0; i < nums.length; i++) {
if(nums[i]!=0)
System.out.print(i+"出现了"+nums[i]+"次!");
}
}
}
全排列
设R={r1,r2,…,rn}是要进行排列的n个元素,Ri=R-{ri}。
集合X中元素的全排列记为perm(X)。
(ri)perm(X)表示在全排列perm(X)的每一个排列前加上前缀得到的排列。
//参考:https://blog.csdn.net/lemon_tree12138/article/details/50986990
public class full_array {
public static void swap(int[] array,int cursor,int i) {
int temp1=array[cursor];
int temp2=array[i];
array[cursor]=temp2;
array[i]=temp1;
}
public static void fullarray(int[] array,int cursor,int end) {
if(cursor==end)
System.out.println(Arrays.toString(array));
else {
for (int i = cursor; i <=end; i++) {
swap(array,cursor,i);
fullarray(array,cursor+1,end);
//交换元素后,进行递归操作,但是在递归结束后,进行下一次循环时,数组已经被交换过一次,不是最原始的
//所以在递归结束后,将数组还原,保持数组一致性
swap(array,cursor,i);
}
}
}
public static void main(String[] args) {
System.out.println("请输入集合大小及其集合:");
Scanner in=new Scanner(System.in);
int n=in.nextInt();
int[] array = new int[n];
int i=0;
for (int j = 0; j < n; j++) {
array[j]=in.nextInt();
}
//System.out.println(Arrays.toString(array));
fullarray(array,0,n-1);
}
}