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;
}