アルゴリズムの設計と分析コースの設計

序文:私は書く時間がありません、私はただコードを書いただけです、私はそれが大丈夫であることを保証することはできません、そして私が選ぶ質問はすべて単純です。バックトラックの質問は自分で間違って書かれていて、他の誰かが書いているのを見つけました。

分割統治:

3.素因数分解

1より大きい正の整数nは、n=x1×x2×…×xmに分解できます。

たとえば、n = 12の場合、8つの異なる分解があります。

12 = 12

12=6×2

12=4×3

12=3×4

12=3×2×2

12=2×6

12=2×3×2

12=2×2×3

入力:

正の整数(10000000未満の正の整数)が指定された場合、データには複数の行があります

出力: 

各データ出力は行であり、これは正の整数nのさまざまな分解の数です。

入力サンプル

12

35

サンプル出力

8

3

#include<iostream>
#include<stdio.h>
using namespace std;
int resolve(int n)
{
	int count = 1, i;					// ans = 1初始表示n = n的情况
	for (i = 2; i * i < n; i++){
        if (n % i == 0)				// i 是 n的因子, n / i也是n的因子
			count += resolve(i) +resolve(n / i);
    }		
	if (i * i == n)					// i是n的因子, 并且i * i == n时只有这一种情况, 左右交换也是一种
		count += resolve(i);
	return count;
}

int main()
{
	int n;
	while(scanf("%d",&n)!=-1){
		cout<<resolve(n);
	}
	
	return 0;
}

動的計画法

4.ステップの問題

問題の説明:n個のステップがあり、人は一度に1つまたは2つのステップを上って、n個のステップを完了する方法をいくつ尋ねます。

実際の状況:行列mが与えられた場合、左上隅から開始して、毎回右または下に移動し、最終的に右下隅に到達することができます。パス内のすべての数値の合計がパスの合計であり、最小パスです。すべてのパスの合計が返されます。mが次のように指定されている場合、パス1、3、1,0、6、1,0は最小パスの合計であり、12を返します。

1 3 5 9

8 1 3 4

5 0 6 1

8 8 4 0

 

 

#include<iostream>
using namespace std;
const int N=10;
int m[N][N];
int main(){ 
    int n;
    cin>>n;
    for(int i=0;i<n;i++){
        for(int j=0;j<n;j++){
            cin>>m[i][j];
        }
    }
    int dp[n][n]={0};
    for(int i=0;i<n;i++){
        for(int j=0;j<n;j++){
            dp[i][j]=m[i][j];
        }
    }
    for(int i=1;i<n;i++){
        dp[i][0]+=dp[i-1][0];
    }
    for(int j=1;j<n;j++){
        dp[0][j]+=dp[0][j-1];
    }
    for(int i=1;i<n;i++){
        for(int j=1;j<n;j++){
            dp[i][j]+=min(dp[i-1][j],dp[i][j-1]);
        }
    }

    cout<<dp[n-1][n-1]<<endl;
    int i=0,j=0;
    cout<<m[i][j]<<" ";
    while(true){
        if(i==n-1&&j==n-1){
            break;
        }
        if(dp[i+1][j]>dp[i][j+1]){
            cout<<m[i][j+1]<<" ";
            j++;
        }
        else{
            cout<<m[i+1][j]<<" ";
            i++;
            
    }

}
}
// 1 3 5 9
// 8 1 3 4
// 5 0 6 1
// 8 8 4 0

よく深い

1.ファイル接続の問題:サイズnの配列Fが与えられた場合、配列要素F[i]はi番目のファイルの長さを表します。ここで、すべてのファイルを1つのファイルにマージする必要があります。ファイルが長いほど、新しいファイルへの接続にかかる時間が長くなります。貪欲アルゴリズムを使用してファイルの接続順序を指定し、ファイルの接続にかかる時間が確実に長くなるようにしてください。最短。 

#include<iostream>
#include<cmath>
#include<algorithm>
using namespace std;
const int N=100;
// 文件连接问题:给定一个大小为n的数组F,数组元素F[i]表示第i个文件的长度。
// 现在需要将所有文件合并成一个文件,
// 文件越长后面连接成新文件花费的时间越长,试给出贪心算法给出文件连接顺序,
// 保证连接文件花费的时间最短。
int main(){
    int n;
    cin>>n;
    int F[N],P[N];
    for(int i=0;i<n;i++){
        cin>>F[i];
    }
    for(int i=0;i<n;i++){
        P[i]=F[i];
    }
    sort(P,P+n);
    for(int i=0;i<n;i++){
        for(int j=0;j<n;j++){
            if(P[i]==F[j]){
                cout<<j+1<<" ";
            }
        }
    }

}
// 5 8 1 3 4 9

 

トレースバック:

1.素数リングの問題

(1)問題の説明:正の整数nを入力し、整数1、2、3、4 ... nのリングを形成して、2つの隣接する整数の合計が素数になるようにします。

(2)サンプル

入力:

6

出力:

1 4 3 2 5 6

1 6 5 2 3 4

(3)ヒント:n=4の場合の検索解空間ツリー。

 

#include<iostream>
#include<cmath>
using namespace std;
int n=0;
const int N=105;
int a[N];       //对应环 
int visit[N]={-1};  //标记数组 0表示未用 1表示已用 
int check(int k)  //判断数字x是否为素数 
{
	int i,n;
	n=(int)sqrt(k);
	for(i=2;i<=n;i++)
		if(k%i==0) return 0;
	return 1;     		
}
void dfs(int step)
{
	if(step==n&&check(a[0]+a[n-1])==1) //全部填满而且第一个元素和最后一个元素满足就输出 
	{
		for(int i=0;i<n;i++)
			cout<<a[i]<<" ";
			cout<<endl;
			return ;
	}
	else
	{
		for(int i=2;i<=n;i++)
		{
			if(visit[i]==0&&check(i+a[step-1])==1){    //i没有被占用且与前一个元素符合 
				a[step]=i;
				visit[i]=1;
				dfs(step+1);
				visit[i]=0;
			}
		}
	}
	
}
int main(void)
{
	cin>>n;
	a[0]=1;  //因为是环所以第一个元素固定 
	visit[1]=1; //1已用 
	dfs(1);	//从第一个元素开始 
	return 0;	
} 

 

おすすめ

転載: blog.csdn.net/qq_56350439/article/details/124768014