编程的笔记

#include
#include
using namespace std;

int main(){
int n,time=0;
cin>>n;
int a[n];
for(int i=0;i<n;i++){
cin>>a[i];
}
for (int i=0;i<n;i++){
int lowindex=i;
bool t=false;
for(int j=n-1;j>i;j–){
if(a[lowindex]>a[j]){
lowindex=j;
t=true;
}
}
if(t==true){
time=time+1;
if(time>1){
cout<<endl;
}
swap(a[i],a[lowindex]);
for(int e=0;e<n-1;e++){
cout<<a[e]<<" ";
}
cout<<a[n-1];
}
}
return 0;
}

简单快速排序
#include<stdio.h>

//算逆序数的主要函数,给每个分层排序
int MergeSort(int s[],int left,int middle,int right){
int i=left,j=middle;
int b[right-left+1];
int index=0;
int sum=0;
int t=0;
while(i<middle&&j<=right){
if(s[i]<s[j]){//哪个大,把哪个放到前面,从大到小排序。设从大到小为正序。
b[index++]=s[j++];
t++;
}
if(s[i]>=s[j]||jright+1){//jright+1是为了防止循坏直接跳出了。 此时应是t*(middle-i),算出middle后面的元素,相对于middle前面的元素,共有多少个逆序数
sum+=t*(middle-i);
b[index++]=s[i++];
t=0;//另t=0后,重新计算,接下来的s[i++]和后面的s[j]构成的逆序数对
}
}
while(i<middle){
b[index++]=s[i++];//若成立,则直接落下来,直接按顺序排到辅助数组里
}
while(j<=right){
b[index++]=s[j++];//若成立,则直接落下来,直接按顺序排到辅助数组里
}
index=0;
for(int i=left;i<=right;i++){
s[i]=b[index++];//将辅助数组,放在上一层数组(这一层的原数组)中,便可以在实现low-mid和mid+1-high的数组的合并
}
return sum;
}

int k=0;

void Merge(int s[],int low,int high){
if(low<high){//一直到high=1时,也就是mid=0时,递归函数的调用才会停止,也就是划分到每个数组中只有一个元素时,停止。
int mid=(low+high)/2;
Merge(s,low,mid);//一直到mid=0时,才会停止划分
Merge(s,mid+1,high);
k=k+MergeSort(s,low,mid+1,high);//MergeSort的调用即可以实现逆序数的计算,又可以合并,划分开的,数组。到上一层继续进行运算。
}
}

int sort(int a[],int n,int x){
int low=0,high=n-1;
Merge(a,low,high);
for(int i=0;i<n;i++){
if(a[i]==x){
return i+1;
}
}
}

7-1 逆序对
#include
#include
using namespace std;

//算逆序数的主要函数,给每个分层排序
int MergeSort(long long int s[],long long int left,long long int middle,long long int right){
long long int i=left,j=middle;
long long int b[right-left+1];
long long int index=0;
long long int sum=0;
long long int t=0;
while(i<middle&&j<=right){
if(s[i]>s[j]){
b[index++]=s[j++];
t++;
}
if(s[i]<=s[j]||jright+1){//jright+1是为了防止循坏直接跳出了。 此时应是t*(middle-i),算出middle后面的元素,相对于middle前面的元素,共有多少个逆序数
sum+=t*(middle-i);
b[index++]=s[i++];
t=0;//另t=0后,重新计算,接下来的s[i++]和后面的s[j]构成的逆序数对
}
}
while(i<middle){
b[index++]=s[i++];//若成立,则直接落下来,直接按顺序排到辅助数组里
}
while(j<=right){
b[index++]=s[j++];//若成立,则直接落下来,直接按顺序排到辅助数组里
}
index=0;
for(int i=left;i<=right;i++){
s[i]=b[index++];//将辅助数组,放在上一层数组(这一层的原数组)中,便可以在实现low-mid和mid+1-high的数组的合并
}
return sum;
}

long long int k=0;

void Merge(long long int s[],long long int low,long long int high){
if(low<high){//一直到high=1时,也就是mid=0时,递归函数的调用才会停止,也就是划分到每个数组中只有一个元素时,停止。
int mid=(low+high)/2;
Merge(s,low,mid);//一直到mid=0时,才会停止划分
Merge(s,mid+1,high);
k=k+MergeSort(s,low,mid+1,high);//MergeSort的调用即可以实现逆序数的计算,又可以合并,划分开的,数组。到上一层继续进行运算。
}
}

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

6-1 单链表去重*
void Unique(NODE *head){
NODE * T=head;//从T指针开始逐个进行操作
NODE * P;//创建P指针
for(T=head->next;T;T=T->next){//因为head有头结点,所有操作从首元节点开始
NODE *pre=T;//pre从开始T指针操作
for(P=T->next;P;P=P->next){//保证T和P不相同(T和pre也不相同)
if(T->data==P->data){
pre->next=P->next;//删除重复的元素
}else
pre=P;//保证pre在P的前面
}
}
}

6-2 LinkList6-查询单链表倒数第K个链点的元素【有题解视频】
int FindInvertedK(LinkList a, int posRevK, DataType *rst){
if (posRevK < 1) {
return 0;
}
LinkList p1 = a;
LinkList p2 = a;

    for (int i = 1; i < posRevK&&p1 != NULL; i++) {
        p1 = p1->next;
    }
    if(p1==NULL){//判断"K超过单链表长度,需要报错"的情况
        return 0;
    }
    while (p1->next != NULL) {
        p1 = p1->next;
        p2 = p2->next;
    }
    *rst=p2->data;
    return 1;
}

6-3 尾部循环的单链表
int find_cycling_position(Node* head){
Node*rab,*tur; //兔子,乌龟
int count=1; //记录结点位置
rab=tur=head; //从起点出发
while(1) {
rab=rab->next->next; //兔子走两步
tur=tur->next; //乌龟走一步
if(rab==tur){//2t+(k-1)-(n+1)=t,t为乌龟走的路程,也是所花时间。所以t=n-k+2
//n为不包括头节点的,结点数。第一次是从头节点开走的,所以为(1+n)
break;
}
}
rab=head; //兔子回到起点
while(rab!=tur){ //因为乌龟在t=n-k+2处,兔子在1处;当t走到终点的下一个节点k处时,兔子
rab=rab->next; //这次速度相同
tur=tur->next;
count++;
}
return count;
}

7-1 表达式转换
#include<bits/stdc++.h>
using namespace std;
stackst;
map<char,int> Rank;
int main(){
Rank[‘+’]=Rank[‘-’]=1;
Rank[‘*’]=Rank[‘/’]=2;
string str;
cin>>str;
bool isfirst=true;
for(int i=0;str[i];i++){
if((isdigit(str[i]))||(str[i]‘.’)||((i0||str[i-1]‘(’)&&(str[i]‘+’||str[i]‘-’))){
if(!isfirst)
cout<<" ";
if(str[i]!=‘+’)
cout<<str[i];
while(str[i+1]
‘.’||isdigit(str[i+1])){
cout<<str[++i];
}
isfirst=false;
}
else{
if(str[i]‘(’){
st.push(str[i]);
}
else if(str[i]
‘)’){
while(!st.empty()&&st.top()!=‘(’){
cout<<" “<<st.top();
st.pop();
}
st.pop();
}
else if(st.empty()||Rank[str[i]]>Rank[st.top()]){
st.push(str[i]);
}
else{
while(!st.empty()&&st.top()!=‘(’){
cout<<” “<<st.top();
st.pop();
}
st.push(str[i]);
}
}
}
while(!st.empty()){
cout<<” "<<st.top();
st.pop();
}
return 0;
}

7-2 Balancing Symbols
#include<stdio.h>
#include<stdlib.h>
#define max 100
typedef struct node{
char data;
struct node* next;
}*Stack;

int isEmpty(Stack s);
void pop(Stack s);
void push(Stack s,char x);
char getTop(Stack s);

main()
{
char str[max],tmp;
int i=0,re[3]={0},flag=0;
Stack s=NULL;
s=(Stack)malloc(sizeof(struct node));
s->next=NULL;

scanf("%s",str);
while(str[i]!='\0')
{
	switch(str[i])
	{
		case '(':
		case '[':
		case '{':
			push(s,str[i]);
			i++;
			break;
		case ')':
			//不匹配 
			if(isEmpty(s))
			{
				re[0]=1;
			}
			else
			{
				tmp=getTop(s);
				if(tmp!='(')
				{
					re[0]=1;
				}
				//匹配
				else
				{
					pop(s);
				} 
			}
			i++;
			break;
		case ']':
			//不匹配 
			if(isEmpty(s))
			{
				re[1]=1;
			}
			else
			{
				tmp=getTop(s);
				if(tmp!='[')
				{
					re[1]=1;
				}
				//匹配
				else
				{
					pop(s);
				} 
			}
			i++;
			break;
		case '}':
			//不匹配 
			if(isEmpty(s))
			{
				re[2]=1;
			}
			else
			{
				tmp=getTop(s);
				if(tmp!='{')
				{
					re[2]=1;
				}
				//匹配
				else
				{
					pop(s);
				} 
			}
			i++;
			break;
		default:
			i++;
			break;
	}
}
while(!isEmpty(s))
{
	tmp=getTop(s);
	switch(tmp)
	{
		case '(':
			re[0]=1;
			break;
		case '[':
			re[1]=1;
			break;
		case '{':
			re[2]=1;
			break;
		default:
			break;
	}
	pop(s);
}
for(i=0;i<3;i++)
{
	if(re[i])
	{
		printf("%d,",i+1);
		flag++;
	}
}
if(flag==0)
{
	printf("0");
}
while(s->next!=NULL)
{
	pop(s);
}
free(s);

}

int isEmpty(Stack s)
{
if(s->nextNULL)
{
return 1;
}
else
{
return 0;
}
}
void pop(Stack s)
{
if(s->next
NULL)
{
printf(“\nempty stack!\n”);
}
else
{
Stack tmp=s->next;
s->next=s->next->next;
free(tmp);
}
}
void push(Stack s,char x)
{
Stack c=(Stack)malloc(sizeof(struct node));
c->data=x;
c->next=s->next;
s->next=c;
c=NULL;
free©;
}
char getTop(Stack s)
{
if(s->next==NULL)
{
printf(“\nempty stack\n”);
}
else
{
return s->next->data;
}
}

6-1 中序输出叶子结点

void InorderPrintLeaves( BiTree T){

if(T==NULL){
    return;
}

if(T->lchild!=NULL){         //左子树不为空,便一直往下检索
    InorderPrintLeaves(T->lchild);
}

if(T->lchild==NULL&&T->rchild==NULL){    //满足此条件便说明找到一片叶子
printf(" ");
printf("%c",T->data );
return;                //返回上一级,在上一级接着判断右孩子是否为空,在右子树继续寻找叶子
}

if(T->rchild!=NULL){            //右子树不为空,便进入右子树检索
    InorderPrintLeaves(T->rchild);
    return;
}

return;              //整个结点(根子树)检索完成,便返回上一级检索其他的结点

}

6-1 二叉树的最长路径问题
//#
int res=0;
template
int getHeight(BinNode* root){
if(!root)
return 0;
int left=getHeight(root->left());
int right=getHeight(root->right());

res=max(res,left+right);//高度是结点数,路径是边数。左子树的高度+右子树高度=这条路径的边数
return 1+max(left,right);

}
template
int LongestPathInBinaryTree(BinNode* root, int& max_dist){
if(!root)
return 0;
getHeight(root);
max_dist=res;
return res;
}

7-2 整型关键字的散列映射
#include<stdio.h>
#include<string.h>
#include<stdlib.h>
#define MAX 10000

int Hash[MAX];

int main(){
for(int i=0;i<MAX;i++){
Hash[i]=-1;
}
int n,p,pos,judge,flag;
scanf(“%d %d”,&n,&p);
for(int i=0;i<n;i++){
scanf(“%d”,&pos);
judge=pos;
flag=1;//判断pos是否已经在hash表中。若存在则不需要插入了
for(int j=0;j<p;j++){
if(Hash[j]judge){
printf(“%d”,j);
flag=0;
break;
}
}
if(flag){//pos不在hash表中,则执行插入操作。
pos=pos%p;//hash(key)
while(Hash[pos]!=-1){
pos++;
if(pos
p){//当已经到了数组最后一个元素,则需要从头Hash[0]继续遍历。
pos=0;
}
}
Hash[pos]=judge;
printf(“%d”,pos);
}
if(i!=n-1){
printf(" ");
}
}
return 0;
}

7-2 中序遍历树并判断是否为二叉搜索树
#include
#include
#include

using namespace std;
const int N=1000;

int g[N][2],p[N]; //g[N][2]存储给定的二叉树,p[N]存储输出二叉树的中序遍历序列
int idx;

void in(int x) //二叉树的中序遍历序列的函数
{
if(x) // 如果这个点存在
{
in(g[x][0]);//递归调用进入左子树
cout<<x<<endl;
p[++idx]=x;
in(g[x][1]);//递归调用进入右子树
}
}

int main()
{
int n,m;
cin>>n>>m;
if(n==0) //当二叉树为空树时,满足二叉搜索树
{
puts(“Yes”);
return 0;
}
for(int i=0;i<n-1;i++) //建树 r 为根 e 为0在左 为1 在右 d 为子节点的值。将二叉树存储进g[N][2]中
{
int r,e,d;
cin>>r>>e>>d;
g[r][e]=d;
}
in(m);//输出二叉树的中序遍历序列
int flage=1;
for(int i=1;i<idx;i++) // 判断是不是 二叉 搜索树
if(p[i]>=p[i+1]) flage=0; // 左节点<中节点<右节点 及树的中序列一定是升序序列。对于二叉搜索树的要求是,中序遍历序列必须是升序的,(且元素无重复)
if(flage) puts(“Yes”);
else
puts(“No”);
return 0;
}

7-1 统计工龄
#include
using namespace std;
int age[51];//51是数组的大小!!!所以[0,50]要设置age[51],不然会出现段错误。也就是数组溢出!
int main(){
int n;
cin>>n;
for(int i=0;i<n;i++){
int a;
cin>>a;
age[a]++;//用hash散列的方法,数组的下标便是元素值。hash(key)=key=年龄。age[年龄]=年龄的次数。
}
for(int i=0;i<51;i++){
if(age[i]>0){
cout<<i<<“:”<<age[i]<<endl;//数组的下标便是年龄,数组存储的元素是下标年龄出现的次数。
}
}
return 0;
}

6-1 堆排序

// 堆化,保持堆的性质
// 从元素a[i],a[lt],a[rt]中找出最大的,并将其下标保存在largest中。
// 如果a[i]是最大的,则以i为根的子树成已为最大堆,程序结束。
// 否则,i的某个子节点中有最大元素,则交换a[i],a[largest]从而使i及其子女满足堆性质。
// 下标为largest的结点在交换后的值为a[i],以该结点为根的子树又有可能违反最大堆性质。因而要对该子树递归调用MaxHeapify。
void HeapAdjust(SqList &L, int i, int size)
{

int lt = 2i, rt = 2i+1;
int largest;
if(lt <= size && L.r[lt].key > L.r[i].key) //右孩子没有超过结点总数,且右孩子大于根节点。
largest = lt; //便把右孩子的下标记下来,给最大值下标
else
largest = i; //否则把根节点的下标记下来,给最大值下标
if(rt <= size && L.r[rt].key > L.r[largest].key) //再和左孩子的值进行比较。左孩子没有超过结点总数,且左孩子大于最大结点的值
largest = rt; //将左孩子下标记下来,给最大值下标
if(largest != i) //如果最大值下标不是根节点,则进行key值的交换
{
int temp = L.r[i].key;
L.r[i].key = L.r[largest].key;
L.r[largest].key = temp;
HeapAdjust(L, largest, size); //继续调用HeapAdjust函数,进行最大堆的排序。
}
}

// 建堆
/自底而上地调用HeapAdjust来将一个数组a[1…size]变成一个最大堆.一定要自下而上的调用,
才能保证调用较小层次的结点的堆排序算法时,较高层次以及满足堆的性质。否则可能导致中间层次出现最大值。
/
// 注意: [size/2]以后的结点为叶子结点,即已经满足堆的性质
void CreatHeap(SqList &L)
{
for(int i=L.length/2; i>=1; --i) //当为满二叉树时,分支节点数n2,总结点数n=2n2+1,叶子节点数=n/2+1=n2+1
HeapAdjust(L, i, L.length);
}

// 堆排序
// 初始调用CreatHeap将a[1…size]变成最大堆
// 因为数组最大元素在a[1],则可以通过将a[1]与a[size]互换达到正确位置
// 现在新的根元素破坏了最大堆的性质,所以调用HeapAdjust调整,
// 使a[1…size-1]成为最大堆,a[1]又是a[1…size-1]中的最大元素,
// 将a[1]与a[size-1]互换达到正确位置。
// 反复调用HeapAdjust,使整个数组成从小到大排序。
// 注意: 交换只是破坏了以a[1]为根的二叉树最大堆性质,它的左右子二叉树还是具备最大堆性质。
// 这也是为何在CreatHeap时需要遍历size/2到1的结点才能构成最大堆,而这里只需要堆化a[1]即可。
void HeapSort(SqList &L)
{
CreatHeap(L );

int len = L.length;
for(int i=L.length; i>=2; --i)
{
int temp = L.r[1].key;
L.r[1].key = L.r[i].key;
L.r[i].key = temp; //因为最大堆只能保证第一个元素L.r[1].key是最大值,不能保证最后一个元素是最小值。
len–; //所以只能通过每次把最大值,也就是L.r[1].key放在数组末尾,才能得到从小到大的序列。
HeapAdjust(L, 1, len); //不包括已排好序的L.r[len]后面的数组元素,在未排好序的部分做最大堆的算法。

}

}

7-1 0-1背包
#include

using namespace std;
const int maxN=105;
const int maxM=1005;
int main(){
int N,M;
int weight[maxM]={0}; //每件物品初始重量为0
int value[maxM]={0}; //每件物品初始价值为0
int dp[maxN][maxM]={0}; //每种情况动态规划(dynamic program)的数组值初始化为0
cin>>N>>M; //第一行输入n件物品和背包容量c
for(int i=1;i<=N;i++){ //接下来的n行,每行有两个数据,分别表示第i(1≤i≤n)件物品的重量和价值。
cin>>weight[i]>>value[i];
}
for(int i=1;i<=N;i++){ //从只能在,前1到n件物品中取时,分别算在容量为0到M的最优情况
for(int j=0;j<=M;j++){
if(weight[i]<=j){
dp[i][j]=max(dp[i-1][j],dp[i-1][j-weight[i]]+value[i]); //动态规划,bottom to up 的思想
}
else{
dp[i][j]=dp[i-1][j];
}
}
}
cout<<dp[N][M];
return 0;
}

6-1 求解资源分配问题(动态规划法)
void Plan(){ //求最优方案dp
/初始化/
dp[m][n]=0;

for(int i=1;i<=m;i++){
    for(int j=1;j<=n;j++){
        pnum[i][j]=0;//初始化:商店i分配的员工数量=0
        dp[m][n]=0;
    }
}
/*********状态转移方程*********/
for(int i=1;i<=m;i++){
    for(int j=1;j<=n;j++){
        for(int p=0;p<=j;p++){
            if(v[i][p]+dp[i-1][j-p]>=dp[i][j]){

//bottom to up得思想,先算出ij较小的最大dp[i][j]值是在哪个p的时候取的;
//再逐渐增大ij,并直接运用较小ij的dp[i][j]的值进行运算。
dp[i][j]=v[i][p]+dp[i-1][j-p];
pnum[i][j]=p;//dp[i][j]最大时,商店i在人数为j,分配的员工数量p
}
}
}
}
}

7-1 h0099. 最长公共子序列
#include<stdio.h>
int main()
{
int n,m;
scanf(“%d %d”,&n,&m);
char n1[n+1],m1[m+1];
for(int i=0;i<n;i++)
{
scanf(“%c”,&n1[i]);
}
for(int i=0;i<m;i++)
{
scanf(“%c”,&m1[i]);
}
int dp[n+1][m+1];
for(int i=0;i<=n;i++)
{
dp[i][0]=0;
}
for(int i=0;i<=m;i++)
{
dp[0][i]=0;
}
for(int i=1;i<=n;i++)
{
for(int j=1;j<=m;j++)
{
if(n1[i-1]==m1[j-1])
{
dp[i][j]=dp[i-1][j-1]+1;//i,j分别表示的是A和B的字符串长度
}
else
{
if(dp[i-1][j]>dp[i][j-1])
{
dp[i][j]=dp[i-1][j];
}else
{
dp[i][j]=dp[i][j-1];
}
}
}
}
printf(“%d”,dp[n][m]);
}

7-1 h0168. 田忌赛马

//类似于动态规划,找到贪心属性即可,即经典田忌赛马的老六思想
#include
#include
using namespace std;
int a[100], b[100];//a是田忌,b是秦王
void SelectSort(int* a, int len)
{
for (int i = 0; i < len; i++)
{
int temp = a[i];
int min = i;
for (int j = i+1; j < len; j++)
{
if (a[j] < temp)6
{
min = j;
temp = a[j];
}

	}
	if (min != i)
	{
		swap(a[i], a[min]);
	}
	
}

}
int main()
{
int n, fastT, fastQ, slowT, slowQ,money;//定义上等马和下等马以及“钱钱”
while (cin >> n && n != 0)//连续输入多组数据
{
for (int i = 0; i < n; i++)
{
cin >> a[i];
}
for (int i = 0; i < n; i++)
{
cin >> b[i];
}
slowT = 0;
slowQ = 0;
fastT = n - 1;
fastQ = n - 1;
money = 0;
SelectSort(a, n);//选择排序将马儿排位
SelectSort(b, n);
for (int i = 0; i < n; i++)//贪心属性为如果上等马打得过上等马,钱钱加一
//,子序列缩短,下等马同理//若都不行,只能劣等打上等,钱钱减一
{
if (a[fastT] > b[fastQ])
{
money++;
fastT–;
fastQ–;
}else
if (a[slowT] > b[slowQ])
{
money++;
slowT++;
slowQ++;
}
else
if(a[slowT]<b[fastQ])
{
money–;
fastQ–;
slowT++;
}

	}
	cout << money * 200 << endl;//最后输出钱钱
}

}

7-1 h0255. 迷宫问题
#include
#include <memory.h>
#include
#include
#include <stdio.h>
#include
#include

const int Max = 1010;

using namespace std;

//结点结构
typedef struct Point
{
int x, y;
}point;

//地图
int maze[Max][Max];
point path[Max][Max]; //走过的路径,每个位置记录他的父位置
int visitied[Max][Max] = {0}; //看结点是否经过

int n;

//上下左右移动的数组,上下左右的顺序
int xMove[4] = {-1, 1, 0, 0};
int yMove[4] = { 0, 0,-1, 1};

point start; // 起点的位置
point endp; //终点的位置

void bfs();
void show();
void showPath();

int main()
{
//迷宫大小为n
cin >> n ;

//初始化迷宫、起点和中点,包一圈围墙好判断
memset(maze, 1, sizeof(maze));
start.x = 1; start.y = 1;
endp.x = n; endp.y = n;

//输入地图
for(int i = 1; i <= n; i++)
    for(int j = 1; j <= n; j++)
        cin >> maze[i][j];


//bfs解决问题

visitied[1][1] = 1; //起始点设为走过
path[1][1].x = -1; path[1][1].y = -1; //设出发点的父结点为-1,-1,用来做输出的停止
bfs();
show();
//showPath();  //测试路径数组

return 0;

}

void bfs()
{
queue q; //存放能走的路,遍历完四个方向后出队
point next; //下一个结点
q.push(start); //将第一个结点范进队列

//遍历所有队列的元素
while(!q.empty())
{
    for(int i = 0; i < 4; i++)
    {
        //设置下一个结点
        //cout<< "当前判断的是" << q.front().x << ' ' << q.front().y << "位置" << endl;
        next.x = q.front().x + xMove[i];
        next.y = q.front().y + yMove[i];


        //如果是0,并且没走过,入队
        if(maze[next.x][next.y] == 0 && visitied[next.x][next.y] == 0)
        {
            //cout<< "结点:" << next.x << ' ' << next.y << "位置可以走" << endl;
            q.push(next);

            visitied[next.x][next.y] = 1;
            //在路径path中,记录该节点的父元素位置
            path[next.x][next.y] = q.front();

        }


    }

    q.pop();

    //cout << d.x << ' ' << d.y << ' ' << d.t << ' ' << d.time << endl;

}

}

void show()
{
//从迷宫终点往回找,并存进栈中
point now, next;
now.x = now.y = n;
stack s;
s.push(now);

//now为起点时结束
while(path[now.x][now.y].x != -1 && path[now.x][now.y].y != -1)
{
    next = path[now.x][now.y]; //在path中找下一个位置的坐标next
    now = next;                //入栈
    s.push(now);
}

//输出
while(!s.empty())
{
    now = s.top();

    cout << now.x-1 << ' ' << now.y-1 << endl;
    s.pop();
}

}

//测试路径
void showPath()
{
for(int i = 1 ;i <= n; i++)
{
for(int j = 1; j <= n; j++)
{
cout << ‘(’ << path[i][j].x << ’ ’ << path[i][j].y << ‘)’ << ’ ';
}
cout << endl;
}
}

7-2 有向图的拓扑序列
#include <bits/stdc++.h>

using namespace std;

#define MAX_LENGTH 1010

vector G[MAX_LENGTH];
int n, m, inDegree[MAX_LENGTH];
stack s;

bool TopologicalOrder() {
int num = 0;
for (int i = 1; i <= n; i++) {
if (inDegree[i] == 0) {
s.push(i);
}
}
while (s.size()) {
int u = s.top();
cout << u << " ";
s.pop();
for (int i = 0; i < G[u].size(); i++) {
int v = G[u][i];
inDegree[v]–;
if (inDegree[v] == 0) {
s.push(v);
}
}
num++;
}
if (num == n) return true;
else return false;
}

int main() {
int x, y;
cin >> n >> m;
memset(inDegree, 0, sizeof(inDegree));
for (int i = 1; i <= m; i++) {
cin >> x >> y;
inDegree[y]++;
if(!G[x].size()) G[x].push_back(y);
else{
G[x].insert(G[x].begin(), y);
}
}
// for( vector::iterator it = G[1].begin();it != G[1].end();it++) cout << *it << " ";
// cout << endl;
if (!TopologicalOrder()) {
cout << endl;
cout << “0” ;
}
return 0;
}

7-2 方格取数
#include<bits/stdc++.h>
using namespace std;
const int INF=0x3f3f3f3f;
const int MAXN=1000005;
const int MAXM=1000005;
int d[MAXN],n,m,p[MAXN],eid,S,T,x[MAXN],y[MAXN],z[MAXN],a[105][105],sz,sum;
struct A{ //灰常正常的最大流(Dinic)
int v,c,next;
}e[MAXM];
void init(){
memset(p,-1,sizeof§);
eid=0;
}
void add(int u,int v,int c){
e[eid].v=v;
e[eid].c=c;
e[eid].next=p[u];
p[u]=eid++;
}
void insert(int u,int v,int c){
add(u,v,c);
add(v,u,0);
}
int bfs(){
memset(d,-1,sizeof(d));
queueq;
d[S]=0;
q.push(S);
while(!q.empty()){
int u=q.front();
q.pop();
for(int i=p[u];i!=-1;i=e[i].next){
int v=e[i].v;
if(e[i].c>0&&d[v]-1){
d[v]=d[u]+1;
q.push(v);
}
}
}
return (d[T]!=-1);
}
int dfs(int u,int flow){
if(u
T) return flow;
int ret=0;
for(int i=p[u];i!=-1;i=e[i].next){
int v=e[i].v;
if(e[i].c>0&&d[v]==d[u]+1){
int tmp=dfs(v,min(flow,e[i].c));
e[i].c-=tmp;
e[i^1].c+=tmp;
flow-=tmp;
ret+=tmp;
if(!flow) break;
}
}
if(!ret) d[u]=-1;
return ret;
}
int Dinic(){
int ret=0;
while(bfs()){
ret+=dfs(S,INF);
}
return ret;
}
int main(){ //以下开始码风突变(中了yjq的膜法)
init();
scanf(“%d%d”, &m, &n);
S=0;T=n*m+1;//建立源点和汇点
for(int i = 1; i <= m; i++){
for(int j = 1; j <= n; j++){
scanf(“%d”, &a[i][j]);
sum += a[i][j];
sz ++;
if((i + j) % 2){
insert(S, sz, a[i][j]);//连向源点
if(j < n) insert(sz, sz + 1, INF);//把有限制条件的连起来,边权注意要尽量大
if(j > 1) insert(sz, sz - 1, INF);
if(i < m) insert(sz, sz + n, INF);
if(i > 1) insert(sz, sz - n, INF);
} else {
insert(sz,T,a[i][j]);//连向汇点
}
}
}
printf(“%d”,sum - Dinic());//总的边权 - 最大流(最小割)
return 0;
}

7-2 胜利者集合
#include <bits/stdc++.h>
using namespace std;
const int N = 1500, M = 10010, INF = 1e9;

int n, m, S, T;
struct Edge {
int to, nxt, flow;
}line[M];
int fist[N], idx, d[N], cur[N];

void add(int x, int y, int z) {
line[idx] = {y, fist[x], z}; fist[x] = idx ++;
line[idx] = {x, fist[y], 0}; fist[y] = idx ++;
}

bool bfs() {
queue q;
memset(d, -1, sizeof d);
q.push(S), d[S] = 0, cur[S] = fist[S];
while(!q.empty()) {
int u = q.front(); q.pop();
for(int i = fist[u]; i != -1; i = line[i].nxt) {
int v = line[i].to;
if(d[v] == -1 && line[i].flow) {
d[v] = d[u] + 1;
cur[v] = fist[v];
if(v == T) return 1;
q.push(v);
}
}
}
return 0;
}

int find(int u, int limit) {
if(u == T) return limit;
int flow = 0;
for(int i = cur[u]; i != -1 && flow < limit; i = line[i].nxt) {
cur[u] = i;
int v = line[i].to;
if(d[v] == d[u] + 1 && line[i].flow) {
int t = find(v, min(line[i].flow, limit - flow));
if(!t) d[v] = -1;
line[i].flow -= t;
line[i ^ 1].flow += t;
flow += t;
}
}
return flow;
}

int dinic() {
int res = 0, flow;
while(bfs()) while(flow = find(S, INF)) res += flow;
return res;
}

int main() {
ios::sync_with_stdio(0); cin.tie(nullptr); cout.tie(nullptr);
cin >> n >> m;
vector<vector> g(n, vector(n, 0));
for(int i = 0; i < m; ++ i) {
int u, v;
cin >> u >> v;
u --, v --;
g[u][v] = 1, g[v][u] = -1;
}
S = n + (n - 2) * (n - 1) / 2;
T = S + 1;
int flag = 0;
for(int i = 0; i < n; ++ i) {
int win = n - 1;
for(int j = 0; j < n; ++ j)
if(g[i][j] == -1) win --;
idx = 0;
memset(fist, -1, sizeof fist);
int cur = n;
for(int j = 0; j < n; ++ j) {
if(j == i) continue;
for(int k = j + 1; k < n; ++ k) {
if(k == i) continue;
add(S, cur, 1);
if(g[j][k] == 0) {
add(cur, j, 1);
add(cur, k, 1);
}
if(g[j][k] == 1)
add(cur, j, 1);
if(g[j][k] == -1)
add(cur, k, 1);
cur ++;
}
}
bool ok = true;
for(int j = 0; j < n; ++ j) {
if(win - 1 - (g[j][i] > 0) < 0) {
ok = false;
break;
}
if(j != i)
add(j, T, win - 1 - (g[j][i] > 0));
}
if(!ok) continue;
if(dinic() == (n - 1) * (n - 2) / 2) {
if(flag) cout << ’ ';
cout << i + 1;
flag = 1;
}
}
cout << ‘\n’;
return 0;
}

7-4 树的遍历
#include
#include
using namespace std;
vectorpost,in,level(100000,-1);
int N;

void ergodic(int root,int start,int end,int index){
int i=start;
if(start>end){
return;
}
while(i<end&&in[i]!=post[root]){
i++;
}
level[index]=post[root];
ergodic(root-1-end+i/左子树根的位置,对于后序遍历序列来说/,start,i-1,2index+1);
ergodic(root-1/右子树根的位置,对于后序遍历序列来说/,i+1,end,2
index+2);
}

int main(){
cin>>N;
post.resize(N);
in.resize(N);
for(int i=0;i<N;i++){
cin>>post[i];
}
for(int i=0;i<N;i++){
cin>>in[i];
}
ergodic(N-1,0,N-1,0);
for(int i=0,cnt=0;i<level.size();i++){
if(level[i]!=-1){
cout<<level[i];
cnt!=N-1?cout<<" ":cout<<endl;
cnt++;
}
}
return 0;
}

7-5 骨牌铺方格
#include
using namespace std;

typedef long long LL;

LL dp[55];

int main(){

dp[1]=1;
dp[2]=2;

for(int i=3;i<=55;i++){
    dp[i]=dp[i-1]+dp[i-2];
}

int n;
while(cin>>n){
    cout<<dp[n]<<endl;
}

return 0;

}

7-6 分而治之
#include
#include
#include
using namespace std;
const int maxm = 10010;
struct node{
int x;
int y;
}edge[maxm];
int v[maxm];
int main()
{
int n,m,k,t,x,y,city,l,p,flag;
scanf(“%d %d”,&n,&m);
for(int i=0;i<m;i++){
scanf(“%d %d”,&edge[i].x,&edge[i].y);
}
scanf(“%d”,&k);
for(int i=0;i<k;i++){
map<int,int> m2;
scanf(“%d”,&t);
for(int j=0;j<t;j++){
scanf(“%d”,&city);
m2[city] = 1;
}
int j = 0;
for(j=0;j<m;j++){
if(m2[edge[j].x]!=1&&m2[edge[j].y]!=1){
printf(“NO\n”);
break;
}
}
if(j>=m){
printf(“YES\n”);
}
}
return 0;
}

7-7 特立独行的幸福
#include
#include
#include
#include
using namespace std;
int fa[10010];
int getfa(int x){//得到各位数字的平方和
int sum=0;
while(x){
sum=sum+(x%10)(x%10);
x=x/10;}
return sum;
}
int find_root(int x){//找到最终指向的根如果这个数是幸福数,则最终一定会指到1,1的根就是自己
int ans=x;
int i=0;
while(fa[ans]!=ans)
{
ans=fa[ans];
i++;
if(i>=10000)
return -1;
}
return ans;
}
bool fun(int x,int n,int m)//判断nm范围内否有数字指向x,即判断是否独立
{
for(int i=n;i<=m;i++)
if(fa[i]==x)
return false;
return true;
}
bool sushu(int x){//判断素数
for(int i=2;i
i<=x;i++)
if(x%i==0)
return false;
return true;
}
int main(){
int n,m;
cin>>n>>m;
int c=0;
for(int i=1;i<=10000;i++)//初始化令所有数字先指向自己
fa[i]=i;
for(int i=1;i<=10000;i++)//令所有数字指向自己的各位平方和
fa[i]=getfa(i);
for(int i=n;i<=m;i++)
{
if(fun(i,n,m)&&find_root(i)1)//如果找根能找到1,而且n到m没有数字指向它,就是特立独行的幸福数
{
cout<<i<<" ";
int flag=1,x=i;
while(getfa(x)!=1)//计算迭代次数
{
x=getfa(x);
flag++;
}
if(sushu(i))flag*=2;
cout<<flag<<endl;
c++;//记录输出了多少个特立独行的幸福数
}
}
if(c
0)
cout<<“SAD”<<endl;
return 0;
}

7-8 冰岛人
#include <bits/stdc++.h>
using namespace std;
#define pis pair<int, string>
int N, M;
string fName, sName, temp;
map<string, pis> Record;
string check(string a, string b) {
int cnt1 = 0, cnt2;
while (a != “”) {
cnt2 = 0;
string b2 = b;
while (b2 != “”) {
if (a == b2 && (cnt1 < 4 || cnt2 < 4)) return “No\n”;
if (cnt1 >= 4 && cnt2 >= 4) return “Yes\n”;
b2 = Record[b2].second;
cnt2++;
}
a = Record[a].second;
cnt1++;
}
return “Yes\n”;
}
int main() {
cin >> N;
while(N–){
cin >> fName >> sName;
if (sName.back() == ‘n’) Record[fName] = {1, sName.substr(0, sName.length() - 4)};
else if (sName.back() == ‘r’) Record[fName] = {0, sName.substr(0, sName.length() - 7)};
else if (sName.back() == ‘m’) Record[fName].first = 1;
else Record[fName].first = 0;
}
cin >> M;
while(M–){
cin >> fName >> temp >> sName >> temp;
if (!Record.count(fName) || !Record.count(sName)) cout << “NA\n”;
else if(Record[fName].first == Record[sName].first) cout << “Whatever\n”;
else cout << check(fName, sName);
}
return 0;
}

7-9 彩虹瓶
#include<stdio.h>
#include<string.h>
int stack[1001] = {114514}, top = 1;

int main()
{
int color_num, capacity, num, i, j;
scanf(“%d%d%d”, &color_num, &capacity, &num);
// 在这里因为题目输入的顺序是反的,所以我们先把栈顶的指针指向最后一个数
int order[color_num + 1], top_order = color_num - 1;
for (i = 0; i < num; i++)
{
// 输入出货顺序
for (j = 0; j < color_num; j++) scanf(“%d”, &order[top_order–]);
top_order = color_num; // 恢复指针
for (j = 1; j <= color_num;)
{
// 本次要找的颜色标号在 出货顺序 或者 暂存货架 的栈顶,那么该栈顶退栈,同时j++
if (stack[top-1] == j) {top–; j++;}
else if (order[top_order-1] == j) {top_order–; j++;}

        // 如果不在 出货顺序 或者 暂存货架 栈顶,并且 出货顺序 栈顶的元素 > 暂存货架 栈顶的元素,break
        else if (order[top_order-1] > stack[top-1]) break;

        // 其余
        else
        {
            stack[top++] = order[--top_order];  // 搬货物
            if (top > capacity + 1) break;  // 如果满了,break
        }
    }   
    if (j == color_num + 1) printf("YES\n");
    else printf("NO\n");

    // 重置两个栈
    memset(stack, 0, sizeof(stack)); top = 1; stack[0] = 114514;
    memset(order, 0, sizeof(order)); top_order = color_num - 1;
}
    return 0;

}

7-10 直捣黄龙
#include
#include
#include
#include
using namespace std;
map<string,int>p;
map<int,string>pp;
int n,m,i,j,cost[201][201],ene[201],fene[201];
int dis[201],cnt[201],visited[201],dist,f[201];
void min(int s)
{
int i,j;
dis[s]=1,visited[s]=1;
for(i=0;i<n;i++)
{
int k=-1,min=999999;
for(j=0;j<n;j++)
{
if(visited[j]0 && cost[s][j]<min)
{
min=cost[s][j];
k=j;
}
}
if(k
-1) break;
visited[k]=1;
for(j=0;j<n;j++)
{
if(visited[j]==0 && cost[s][j]>cost[s][k]+cost[k][j])
{
f[j]=k;
dis[j]=dis[k];
cost[s][j]=cost[s][k]+cost[k][j];
fene[j]=fene[k]+ene[j];
cnt[j]=cnt[k]+1;
}
else if(visited[j]==0 && cost[s][j]==cost[s][k]+cost[k][j])
{
dis[j]=dis[j]+dis[k];
if(cnt[j]<cnt[k]+1)
{
f[j]=k;
fene[j]=fene[k]+ene[j];
cnt[j]=cnt[k]+1;
}
else if(cnt[j]==cnt[k]+1)
{
if(fene[j]<fene[k]+ene[j])
{
f[j]=k;
fene[j]=fene[k]+ene[j];
}
}
}
}
}
}
int main()
{
string begin,end,path,name,x,y;
cin>>n>>m>>begin>>end;
for(i=0;i<n;i++)
{
for(j=0;j<n;j++) cost[i][j]=cost[j][i]=999999;
}
p[begin]=0,pp[0]=begin;
for(i=1;i<n;i++)
{
cin>>name>>ene[i];
p[name]=i;
pp[i]=name;
fene[i]=ene[i];
cnt[i]=1;
dis[i]=1;
}
while(m–)
{
cin>>x>>y>>dist;
cost[p[x]][p[y]]=cost[p[y]][p[x]]=dist;
}
min(0);
int goal=p[end],index=p[end];
path=path+begin;
stackss;
ss.push(end);
while(f[index]!=0)
{
ss.push(pp[f[index]]);
index=f[index];
}
while(!ss.empty())
{
path=path+“->”+ss.top();
ss.pop();
}
cout<<path<<endl;
cout<<dis[goal]<<" “<<cost[0][goal]<<” "<<fene[goal]<<endl;
return 0;
}

7-2 A-B
#include
#include
#include
using namespace std;

int main(){
string A,B;
getline(cin,A);
getline(cin,B);
int lenA=A.size();
int lenB=B.size();
int flag=0;
for(int i=0;i<lenA;i++){
for(int j=0;j<lenB;j++){
if(A[i]B[j]){
flag=1;
break;
}
}
if(flag
0){
cout<<A[i];
}
else{
flag=0;
}
}
cout<<endl;
return 0;
}

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

罗娜mei

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值