中国矿业大学算法实验课—复习

字典全排序--用next_permutation

题目描述

    输入一个可能含有重复字符的字符串,打印出该字符串中所有字符的全排列。

输入

单组测试数据,输入数据是一个长度不超过10个字符的字符串,以逗号结尾。

输出

打印出该字符串中所有字符的全排列。以字典序顺序输出,用空格分隔。

样例输入

abc,

样例输出

abc acb bac bca cab cba

字符全排列

#include <iostream>
#include<algorithm>
using namespace std;
 
int main() {
	string str;
	cin>>str;

  	str.erase(str.end() - 1);

	sort(str.begin(),str.end());
	do{
		cout<<str<<" ";
	}while(next_permutation(str.begin(),str.end()));//next_permutation()会取得[first,last)所标示之序列的下一个排列组合,如果没有下一个排列组合,便返回false;否则返回true。
	return 0;
}

数字全排列

#include <iostream>
#include<algorithm>
using namespace std;
 
int main(int argc, char** argv) {
	int a[4]={1,2,3,4};
	sort(a,a+4);
	do{
		//cout<<a[0]<<" "<<a[1]<<" "<<a[2]<<" "<<a[3]<<endl;
		for(int i=0;i<4;i++)
		    cout<<a[i]<<" ";
		cout<<endl;
	}while(next_permutation(a,a+4));
	return 0;
}

直接算出集合{1, 2, ..., m}的第n个排列?

#include <iostream>
#include<algorithm>
using namespace std;
 
int main(int argc, char** argv) {
	int a[7]={1,2,3,4,5,6,7};
	sort(a,a+7); 
	int n=1;
	do{
		if(n==3){
		    for(int i=0;i<7;i++)
              cout<<a[i];
            cout<<endl;
        break;
		}
        n++;
    }while(next_permutation(a,a+7));
	return 0;
}

 

 

#include<bits/stdc++.h>
//using namespace std;
//
//int path[10];
//int state[10];//记录数字是否被用过 
//
//int n;
//
//void dfs (int u)//第u个格子装数据 
//{
//	if(u>n)
//	{
//		for(int i=1;i<=n;i++)
//		{
//			cout<<path[i]<<" ";
//			
//	    }
//		cout<<endl;	
//			
//	}
//
//
//	
//	for(int i=1;i<=n;i++)
//	{
//		if(!state[i]) 
//		{
//			path[u]=i;
//			state[i]=1;
//			dfs(u+1);
//			state[i]=0;//回溯,还原状态 
//			 
//		}
//	}
//}
//
//int main()
//{
//	cin>>n;
//	dfs(1);

跳台阶

 

题目描述

一只青蛙一次可以跳上1级台阶,也可以跳上2级。求该青蛙跳上一个n级的台阶总共有多少种跳法。

输入

多组测试样例。每组测试样例包含一个整数n。(1<=n<=100)

输出

每组测试样例输出一行,表示青蛙跳上n级台阶的跳法数量.

所得到的结果模1000000007
 

#include <bits/stdc++.h>
using namespace std;
long long a[110];  //必须用长整型存,后期跳台阶数目会很大
int n;
int main() 
{

    a[1]=1;
	a[0]=1;     //本来a[0]应该是0,分析一下a[2]=2,a[1]+a[0]=1,不符合实际,所以边缘条件要调整一下
    for(int i=2;i<=100;i++)
    a[i]=(a[i-1]+a[i-2])%1000000007;     //取模,避免越界
    
    while(cin>>n)
    {
     cout<<a[n]<<endl;  
    } 
    
}

最长公共子串(数据范围比较小,不用优化)

题目描述

一个字符串A的子串被定义成从A中顺次选出若干个字符构成的串。如A=“cdaad" ,顺次选1,3,5个字符就构成子串" cad" ,现给定两个字符串,求它们的最长共公子串。

输入

第一行两个字符串用空格分开。两个串的长度均小于2000 。

输出

最长子串的长度。

线性dp

#include<iostream>
#include<algorithm>
using namespace std;
string word1;
string word2;
int n1,n2;
int s[2000][2000];

void dp()
{
    
    for (int i = 1; i <= n1; i++)
    {
        for (int j = 1; j <= n2; j++)
        {
            if (word1[i-1] == word2[j-1])
            {
                s[i][j] = s[i - 1][j - 1]+1; 
               //s[i][j]代表当word1长度为i,word2长度是j时,最长公共子串长度
               //DP在从长度从小往大存
            }
            else
            {
                   s[i][j] = max(s[i - 1][j], s[i][j - 1]);
            }
        }
    }


}
int main()
{
    cin>>word1>>word2;
    n1=word1.length();
    n2=word2.length();
    dp();
    cout << s[n1][n2];//

}

最长上升子序列

742da68a8158417c97a951f70efb5eaa.jpeg

 

#include<iostream>
using namespace std;
int h[1000][4];
int main()
{
    int n;
    cin>>n;
    for(int i=0;i<n;i++)
    {
        cin>>h[i][1];
        h[i][2]=1;
        h[i][3]=1;
        
    }
    for(int i=0;i<n;i++)
    {
        for(int j=0;j<i;j++)
        {
            if(h[j][1]<h[i][1]&&h[i][2]<=h[j][2]) h[i][2]=h[j][2]+1;
            if(h[j][1]>h[i][1]&&h[i][3]<=h[j][3]) h[i][3]=h[j][3]+1;
        }
    }
    int maxx=0;
    for(int i=0;i<n;i++)
    {
        maxx=max(maxx,h[i][2]);
        maxx=max(maxx,h[i][3]);
    }
    cout<<maxx;
}

前缀和

#include<iostream>
using namespace std;
int n,L,r,t,ans=0;
int A[605][605]={0};
int sum[605][605]={0};
bool judgeBlack(int x,int y)
{
	int maxx = min(n, x+r);
	int maxy = min(n, y+r);
	int minx = max(1, x-r);
	int miny = max(1, y-r);
	int s = sum[maxx][maxy] - sum[maxx][miny-1] - sum[minx-1][maxy] + sum[minx-1][miny-1];
	int count = (maxx-minx+1)*(maxy-miny+1);
	double test = s/(double)count;
	return test<=t;
}
int main()
{
	cin>>n>>L>>r>>t;
	for(int i=1;i<=n;i++)
	{
		for(int j=1;j<=n;j++)
		{
			cin>>A[i][j];
			sum[i][j] = sum[i-1][j]+sum[i][j-1] - sum[i-1][j-1]+A[i][j];
		}
	}
	for(int i=1;i<=n;i++)
	{
		for(int j=1;j<=n;j++)
			if(judgeBlack(i,j))
				ans++;
	}
	cout<<ans;
	return 0;
}

跳跃游戏二

题目描述

给定一个非负整数数组,假定你的初始位置为数组第一个下标。数组中的每个元素代表你在那个位置能够跳跃的最大长度。你的目标是到达最后一个下标,并且使用最少的跳跃次数。例如:A = [2,3,1,1,4],到达最后一个下标的最少跳跃次数为 2。(先跳跃11步,从下标0到1,然后跳跃3步,到达最后一个下标。一共两次)

 

输入

第一行输入一个正整数n(1≤n≤100),接下来的一行,输入n个整数,表示数组A。

 

输出

最后输出最少的跳跃次数。

 

 

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值