2022年春季学期《算法分析与设计》练习16

1479: N皇后问题

题目描述

使用回溯法求解N后问题。

 

输入

皇后的个数。

输出

每一种方案及总方案数。

样例输入 Copy

4

样例输出 Copy

0 1 0 0
0 0 0 2
3 0 0 0
0 0 4 0
----------------
0 0 1 0
2 0 0 0
0 0 0 3
0 4 0 0
----------------
总方案数为:2

 

import java.util.Scanner;
 
public class Main{
static final int N=20;   //最多放皇后的个数
    static int[] q =new int[N];         //各皇后所在的行号
    static int cont = 0;     //统计解得个数
    //输出一个解
  public static void print(int n)
    {
        int i,j;
        cont++;
//  printf("第%d个解:",cont);
        for(i=1;i<=n;i++)
//         printf("(%d,%d)",i,q[i]);
//  printf("\n");
            for(i=1;i<=n;i++)        //行
            {
                for(j=1;j<=n;j++)   //列
                {
                    if(q[i]!=j)
                        System.out.printf("0 ");
                    else
                        System.out.printf("%d ",i);
                }
                System.out.println();;
                if(i==n)
                    System.out.printf("----------------\n");
            }
    }
    //检验第i行的k列上是否可以摆放皇后
  static  boolean find(int i,int k)
    {
        int j=1;
        while(j<i)  //j=1~i-1是已经放置了皇后的行
        {
            //第j行的皇后是否在k列或(j,q[j])与(i,k)是否在斜线上
            if(q[j]==k ||Math.abs(j-i)==Math.abs(q[j]-k))
                return false;
            j++;
        }
        return true;
    }
    //放置皇后到棋盘上
  static  void place(int k,int n)
    {
        int j;
        if(k>n)
            print(n);
        else
        {
            for(j=1;j<=n;j++)   //试探第k行的每一个列
            {
                if(find(k,j))
                {
                    q[k] = j;
                    place(k+1,n);  //递归总是在成功完成了上次的任务的时候才做下一个任务
                }
            }
        }
    }
 
    public static void main(String[] args) {
 
//        clock_t start,finish;
        Scanner scan=new Scanner(System.in);
        int n=scan.nextInt();
//  printf("请输入皇后个数:");
//        scanf("%d",&n);
//        start = clock();
//  printf("\n使用非递归回溯法解决 %d 皇后问题时的运行情况\n",n);
        place(1,n);
//        finish = clock();
//  printf("共有 %d 种不同的排列 计算用时%.2fms \n",count, (double) (finish - start));
        System.out.printf("总方案数为:%d",cont);
//  system("pause");
    }
}

1495: 0-1背包问题(回溯法)

题目描述

有n个物品,第i个物品重量为wi,价值为vi,现有一背包容量为C,要求把物品装入背包得到最大价值,并且要求出这些选取的物品。 要求用回溯法求解。

输入

多组测试数据,请处理到文件尾,一个整数表示物品的数量n,后一行有n个整数,代表价值,再后一行有n个整数,代表重量,最后有一个整数C代表背包容量,1<=n<=15,1<=vi<=30,1<=wi<=30,1<=C<=80。

输出

背包的最大总价值和所选取的物品,如果选取的方案有多种,请输出字典序最小的那种方案,每组测试数据应输出一行,在这里字典序最小的意思是,我们假设存在两种不同方案S,T所能得到的总价值相同且是最大的,对于方案S种选取|S|种物品,方案T选取|T|种物品,对于i=1,2...j-1,我们有si = ti,但sj < tj,则方案的S的字典序比方案T的字典序要小。由于没有使用special judge,所以如果选取得方案是S,请按照从小到大的顺序输出方案S中的物品下标。

样例输入 Copy

5
6 3 6 5 4
2 2 4 6 5
8

样例输出 Copy

15 1 2 3
import java.util.Scanner;
public class Main {
    static int v[];
    static int w[];
     
    static int best;
     
    static int  maxsort;
    
    public static void main(String[] args) {
        Scanner in = new Scanner(System.in);
        while(in.hasNext()) {
            int n = in.nextInt();
           v = new int[n];
           
             w = new int[n];
              for(int i = 0;i<n;i++) {
                v[i] = in.nextInt();
            }
            for(int i = 0;i<n;i++) {
                w[i] = in.nextInt();
            }
          int m = in.nextInt();
            best = 0;
            maxsort = 10000;
            int[] c = new int[n];
             
            int[] d = new int[n];
               solve(0,0,v,w,m);
            maxsort(0,0,0,v,w,c,d,m);
             
            System.out.print(best);
            for(int i = 0;i<n;i++) {
                if(d[i]!=0) {
                    System.out.print(" ");
                    System.out.print(i+1);
                }
            }
            System.out.println();
        }
    }
      
    public static void solve(int i,int p,int[] a,int[] b,int m) {
        if(i<a.length) {
            if(b[i]<=m) {
                p = p+a[i];
                m = m-b[i];
                solve(i+1,p,a,b,m);
                p = p-a[i];
                m = m+b[i];
            }
            solve(i+1,p,a,b,m);
        }
        else {
            if(p>best) {
                best = p;
            }
        }
    }
      
    public static void maxsort(int i,int p,int q,int[] a,int[] b,int[] c,int[] d,int m) {
        if(i<a.length) {
            if(b[i]<=m) {
                c[i] = 1;
                p = p+a[i];
                m = m-b[i];
                q = q+i+1;
                maxsort(i+1,p,q,a,b,c,d,m);
                c[i] = 0;
                p = p-a[i];
                m = m+b[i];
                q = q-i-1;
            }
            c[i] = 0;
            maxsort(i+1,p,q,a,b,c,d,m);
        }
        else {
            if(p==best) {
                if(maxsort>q) {
                    maxsort = q;
                    for(int j = 0;j<a.length;j++) {
                        d[j] = c[j];
                    }
                }
            }
        }
    }
}

1950: 排列蛋卷

题目描述

刚考完研的TC同学这段时间在家闲得慌,因此他决定学点新手艺。今天他学习的内容是:做蛋卷。
由于是第一次做蛋卷,TC同学做出来蛋卷长短不一。看着这些长度都不一样的蛋卷,TC同学的强迫症又犯了。他希望能够拿出其中部分蛋卷,使得留下来的蛋卷能够按照长度从大到小的次序排列
请问他最少需要拿出多少根蛋卷

输入

单组输入,对于每一组测试数据,第1行N表示蛋卷的总数量(n<=1000)。 
第2行包含N个正整数,分别表示每一根蛋卷的长度。(单位:厘米) 
保证在同一组输入数据中每一根蛋卷的长度均不一样。

输出

输出最少需要拿出的蛋卷数量。

样例输入 Copy

5
15 18 17 11 12

样例输出 Copy

2
import java.util.Scanner;
 
public class Main{
     
     
public static void main(String[] args)   {
     
 
   Scanner in=new Scanner(System.in);
 
    
   while(in.hasNext()){
     
       int n=in.nextInt();
    int a[]=new int[n];
    for(int i=0;i<n;i++){
        a[i]=in.nextInt();
    }
    int b[]=new int[n];
    b[0]=1;
    for(int i=1;i<n;i++){
        int temp=0;
        for(int j=i-1;j>=0;j--){
            if(a[i]<a[j]&&b[j]>temp){
                b[i]=b[j];
                temp=b[j];
            }
        }
        b[i]=b[i]+1;
    }
     
    int max=b[0];
    for(int i=1;i<n;i++){
        if(b[i]>max){
            max=b[i];
             
        }
    }
     
    int result=n-max;
     
    System.out.println(result);
       
       
    }
}
 
 
 
}

1754: X星人的基因

题目描述

X星人的基因由A、B、C、D、E五种不同的结构组合而成。
如果两个性别不同的X星人的基因序列相似度大于50%,按照X星的法律他们是禁止结婚的,等于50%据说还是可以的。
那么基因的相似度怎么计算呢?分别从两个人身上取长度均为N的基因片段,如果它们的最长公共子序列为M,则相似度=M/N。是不是很简单呢?
现在给你两段X星人的基因序列片段,请你判断他们是不是可以结婚?

输入

每一组测试数据包含3行,
第1行数字N表示待比较基因序列片段的长度,N<=10^3。
第2行和第3行为两个长度为N的基因序列片段。
输入0表示结束。

输出

两个X星人是否可以结婚,如果可以输出”Yes“,如果不可以输出”No“。

样例输入 Copy

8
A B C D E A B C
A C C D C B A E
6
A B C D E E
A E D C B B
0

样例输出 Copy

Yes
Yes
#include<iostream>
#include<cmath>
 
using namespace std;
char a[10010],b[10010];
int dp[1010][1010]={0};
 
 
int main(){
    int n;
    while(cin>>n&&n){
        for(int i=0;i<n+10;i++){     //初始化
            for(int j=0;j<n+10;j++){
                dp[i][j]=0;
            }
        }
        for(int i=0;i<n;i++) cin>>a[i];       //输入
        for(int i=0;i<n;i++) cin>>b[i];
         
        for(int i=0;i<n;i++){         //动态规划求出最长公共子序列
            for(int j=0;j<n;j++){
                if(a[i]==b[j]){
                    dp[i][j]=dp[i-1][j-1]+1;
                } 
                else {
                    dp[i][j]=max(dp[i-1][j],dp[i][j-1]);
                }
            }
        }
         
        int num=dp[n-1][n-1];             //进行计算
        double nu=(double)num/n;
//      cout<<num<<endl;
        if(nu>0.5) cout<<"No"<<endl;       //判断输出结果
        else cout<<"Yes"<<endl;
    }
     
     
     
    return 0;
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

君临๑

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

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

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

打赏作者

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

抵扣说明:

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

余额充值