洛谷题单:【算法1-3】暴力枚举

(1)P2241 统计方形(数据加强版)
这道题经过数据加强后,只能通过两个循环解决,那么我们肯定是枚举长和宽的长度,然后找规律发现,在确定了长度和宽度后,能横向平移,或者纵向平移的次数是:(大矩阵的长度-当前矩阵的长度+1),宽度也是同理,那么我们可以知道,长和宽移动的次数相乘便是这个形状的小矩形的个数。然后枚举所有小矩形的形状即可。

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;

public class Main {
	public static void main(String[] args) throws IOException {
		BufferedReader br=new BufferedReader(new InputStreamReader(System.in));
		String[] s=br.readLine().split(" ");
		long n=Long.valueOf(s[0]),m=Long.valueOf(s[1]);
		long sum1=0,sum2=0;
		for(int i=1;i<=n;i++) {
			for(int j=1;j<=m;j++) {
				if(i==j) sum1+=(n-i+1)*(m-j+1);
				else sum2+=(n-i+1)*(m-j+1);
			}
		}
		System.out.println(sum1+" "+sum2);
	}
}

(2)P2089 烤鸡
一道朴素的搜索问题,每种调料可以选1-3克,一共有10种调料,那么我们便搜索所有情况,把符合题目要求的输出即可。

import java.util.ArrayList;
import java.util.Arrays;
import java.util.Scanner;

public class Main {
	static int n,res;
	static int[] arr=new int[10];
	static int[][] arr2=new int[10000][10];
	public static void main(String[] args) {
		Scanner sc=new Scanner(System.in);
		n=sc.nextInt();
		dfs(0,0);
		System.out.println(res);
		for(int i=0;i<res;i++) {
			for(int j=0;j<10;j++) {
				System.out.print(arr2[i][j]+" ");
			}
			System.out.println();
		}
	}
	public static void dfs(int i,int sum) {
		if(sum==n&&i==10) {
			arr2[res]=Arrays.copyOf(arr, arr.length);
			res++;
		}
		if(sum>=n||i>=10) {
			return;
		}
		for(int j=1;j<=3;j++) {
			arr[i]=j;
			dfs(i+1,sum+j);
		}
	}
}

(3)P1618 三连击(升级版)
首先这道题用全排列搜索也是可以的。但也可以用枚举,让i从1枚举到1000/最大的那个比例,然后把i分别乘3个比例,然后判断3个数是否满足条件,首先最大的那个数不能超过1000,其次,判断是否每个数字都出现过,这里有个巧妙的方法,就是放进一个1-9的桶里面,然后扫描这个桶判断是否每个数都出现过。最后如果没有有符合条件的解那么输出No!!!

import java.util.Arrays;
import java.util.Scanner;

public class Main {
	public static void main(String[] args) {
		Scanner sc=new Scanner(System.in);
		int a=sc.nextInt(),b=sc.nextInt(),c=sc.nextInt();
		int[] arr=new int[10];
		boolean flag=false;
		for(int i=1;i<=1000/c;i++) {
			boolean sign=true;
			int k1=i*a,k2=i*b,k3=i*c;
			if(k3>999)break;
			while(k1>0) {arr[k1%10]++;k1/=10;}
			while(k2>0) {arr[k2%10]++;k2/=10;}
			while(k3>0) {arr[k3%10]++;k3/=10;}
			for(int j=1;j<10;j++)if(arr[j]==0) {sign=false;break;}
			Arrays.fill(arr, 0);
			if(sign) {
				flag=true;
				System.out.println(i*a+" "+i*b+" "+i*c);
			}
		}
		if(!flag)System.out.println("No!!!");
	}
}

(4)P1036 选数
又是一道朴实的搜索题,把n个数据存储起来,然后搜索每种情况,即每个数字选择加或者不加。最后看这些选择的数和是否为素数并且这些数的个数要等于K。


import java.util.Scanner;

public class Main {
	static int n,k;
	static int[] arr;
	public static void main(String[] args) {
		Scanner sc=new Scanner(System.in);
		n=sc.nextInt();
		k=sc.nextInt();
		arr=new int[n];
		for(int i=0;i<n;i++) {
			arr[i]=sc.nextInt();
		}
		dfs(0,0,0);
		System.out.println(count);
	}
	static int count=0;
	public static void dfs(int i,int kk,int sum) {
		if(kk==k) {
			if(isP(sum)) {
				count++;
			}
			return;
		}
		if(i==n) {
			return;
		}
		dfs(i+1,kk+1,sum+arr[i]);//选
		dfs(i+1,kk,sum); //不选
	}
	public static boolean isP(int n) {
		for(int i=2;i*i<=n;i++) {
			if(n%i==0) {
				return false;
			}
		}
		return true;
	}
}

(5)P1157 组合的输出
搜索题目。从1-n搜索,对于每个数可以选择选或不选,当选择的数目达到r了的时候,就输出选择的数字

import java.util.Scanner;

public class Main {
	static int n,m;
	static int[] arr;
	public static void main(String[] args) {
		Scanner sc=new Scanner(System.in);
		n=sc.nextInt();m=sc.nextInt();
		arr=new int[m];
		dfs(0,0);
	}
	public static void dfs(int index,int k) {
		if(k==m) {
			for(int i=0;i<m;i++) {
				System.out.printf("%3d",arr[i]);
			}
			System.out.println();
			return;
		}
		if(index==n) {
			return;
		}
		arr[k]=index+1;
		dfs(index+1,k+1);
		dfs(index+1,k);
	}
	
}

(6)P1706 全排列问题
这道题赤裸裸的用搜索进行全排列,c++能过,但是Java会超时一个点,因为java太慢了。。

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.PrintWriter;

public class Main {
	static int n;
	static int[] arr;
	static boolean[] vis;
	static PrintWriter out;
	public static void main(String[] args) throws  IOException {
		BufferedReader br=new BufferedReader(new InputStreamReader(System.in));
		out=new PrintWriter(System.out);
		n=Integer.valueOf(br.readLine());
		vis=new boolean[n+1];
		arr=new int[n];
		dfs(0);
		out.close();
	}
	public static void dfs(int index) {
		if(index==n) {
			for(int i=0;i<n;i++) {
				out.printf("%5d",arr[i]);
			}
			out.println();
		}
		for(int i=1;i<=n;i++) {
			if(!vis[i]) {
				vis[i]=true;
				arr[index]=i;
				dfs(index+1);
				vis[i]=false;
			}
		}
	}
}

(7)P1088 火星人
非常针对java的一道题目,如果用c++的全排列函数几行代码就搞定了。如果自己用递归写全排列的话,首先要定位到外星人给出的那个排列,然后慢慢进行排列下一次,直到达到科学家加的那个数字次数。这里有个巧妙的地方是第一步首先要定位到外星人的那个排列。
PS:因为java的递归最大只能10000层,仍然有一个点会过不了。

import java.util.Scanner;

public class Main{
	static boolean sign=false;
	static int num=0,n,m;
	static int[] arr;
	static boolean[] vis;
	public static void main(String[] args) {
		Scanner sc=new Scanner(System.in);
		n=sc.nextInt();m=sc.nextInt();
		arr=new int[n+1];
		vis=new boolean[n+1];
		for(int i=1;i<=n;i++) {
			arr[i]=sc.nextInt();
		}
		dfs(1);
	}
	public static void dfs(int index) {
		if(sign) return ;
		if(index==n+1) {
			num++;
			if(m+1==num) {
				for(int i=1;i<=n;i++) {
					System.out.print(arr[i]+" ");
				}
				System.out.println();
				sign=true;
			}
			return;
		}
		for(int i=1;i<=n;i++) {
			if(num==0)i=arr[index];
			if(!vis[i]) {
				arr[index]=i;
				vis[i]=true;
				dfs(index+1);
				vis[i]=false;
			}
		}
	}
}

(8)P3392 涂国旗
数据量很小,可以直接暴力枚举,先两重循环枚举每个颜色所占的行数,然后计算需要涂的格子总和数,维护一个最小值。

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;

public class Main {
	public static void main(String[] args) throws IOException {
		BufferedReader br=new BufferedReader(new InputStreamReader(System.in));
		String[] s=br.readLine().split(" ");
		int n=Integer.valueOf(s[0]),m=Integer.valueOf(s[1]);
		char[][] arr=new char[n][m];
		for(int i=0;i<n;i++) {
			arr[i]=br.readLine().toCharArray();
		}
		int min=Integer.MAX_VALUE;
		for(int i=0;i<n-2;i++) {
			for(int j=i+1;j<n-1;j++) {
				int sum=0;
				for(int a=0;a<=i;a++) 
					for(int k=0;k<m;k++) 
						if(arr[a][k]!='W')sum++;
				for(int b=i+1;b<=j;b++) 
					for(int k=0;k<m;k++) 
						if(arr[b][k]!='B')sum++;
				for(int c=j+1;c<n;c++) 
					for(int k=0;k<m;k++) 
						if(arr[c][k]!='R')sum++;
			min=Math.min(min, sum);
			}
		}
		System.out.println(min);
	}
}

(9)P3654 First Step (ファーストステップ)
横着找每一遍,再竖着找一遍。复杂度o(n^3)完全可以过,找到符合的就计数加1,因为数据很小,但优化一下到达 o(n^2)复杂度,一次性找到一行或一列中连续符合的。

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;

public class Main {
	public static void main(String[] args) throws IOException {
		BufferedReader br=new BufferedReader(new InputStreamReader(System.in));
		String[] s=br.readLine().split(" ");
		int n=Integer.valueOf(s[0]),m=Integer.valueOf(s[1]),k=Integer.valueOf(s[2]);
		char[][] arr=new char[n][m];
		for(int i=0;i<n;i++) {
			arr[i]=br.readLine().toCharArray();
		}
		int sum=0;
		for(int i=0;i<n;i++) {
			int q=0;
			for(int j=0;j<m;j++) {
				if(arr[i][j]=='.') {
					q++;
				}
				else {
					if(q>=k) {
						sum+=q-k+1;
					}
					q=0;
				}
			}
			if(q>=k) {
				sum+=q-k+1;
			}
		}
		for(int i=0;i<m;i++) {
			int q=0;
			for(int j=0;j<n;j++) {
				if(arr[j][i]=='.') {
					q++;
					
				}
				else {
					if(q>=k) {
						sum+=q-k+1;
					}
					q=0;
				}
			}
			if(q>=k) {
				sum+=q-k+1;
			}
		}
		if(k==1) {
			System.out.println(sum/=2);
		}
		else {
			System.out.println(sum);
		}
	}
}

(10)P1217 [USACO1.5]回文质数 Prime Palindromes
很多次在题单看到这道题了,就是根据规律删去大部分数据。然后对剩下的数据进行搜索。规律大体就是,一二位可以直接判断,四六八位的数字不可能是回文质数所以不用搜索,而剩下的位数,只有首位和末尾都奇数才可能是回文质数。

import java.util.Scanner;

public class Main {
	static int[] a=new int[100000];
	public static boolean prime(int n) {
		for(int i=2;i*i<=n;i++) {
			if(n%i==0) {
				return false;
			}
		}
		return true;
	}
	public static void main(String[] args) {
		Scanner sc=new Scanner(System.in);
		int x=sc.nextInt(),y=sc.nextInt();
		int p=0;
		for(int i=2;i<10;i++) {  //一位数
			if(prime(i)) {
				a[p++]=i;
			}
		}
		a[p++]=11;   //两位数
		for(int i=1;i<10;i+=2) {  //三位数
			for(int j=0;j<10;j++) {
				if(prime(i*101+j*10)) {
					a[p++]=i*101+j*10;
				}
			}
		}
		for(int i=1;i<10;i+=2) {  //五位数
			for(int j=0;j<10;j++) {
				for(int k=0;k<10;k++) {
					if(prime(i*10001+j*1010+k*100)) {
						a[p++]=i*10001+j*1010+k*100;
					}
				}
			}
		}
		for(int i=1;i<10;i+=2) {  //五位数
			for(int j=0;j<10;j++) {
				for(int k=0;k<10;k++) {
					for(int l=0;l<10;l++) {
						if(prime(i*1000001+j*100010+k*10100+l*1000)) {
							a[p++]=i*1000001+j*100010+k*10100+l*1000;
						}
					}
				}
			}
		}
		for(int i=0;i<p;i++) {
			if(x<=a[i]&&a[i]<=y) {
				System.out.println(a[i]);
			}
		}
	}
}

(11)P1149 火柴棒等式
两个循环,枚举所有左边两个数字,然后把他们加起来,判断这种情况是否符合条件。也就是火柴数是否刚好用完


import java.util.Scanner;

public class Main {
	static int[] m= {6,2,5,5,4,5,6,3,7,6};
	public static int f(int n) {
		if(n==0) {
			return 6;
		}
		int sum=0;
		while(n>0) {
			sum+=m[n%10];
			n/=10;
		}
		return sum;
	}
	public static void main(String[] args) {
		Scanner sc=new Scanner(System.in);
		int n=sc.nextInt();
		int cnt=0;
		for(int i=0;i<1000;i++) {
			for(int j=0;j<1000;j++) {
				if(f(i)+f(j)+4+f(i+j)==n) {
					cnt++;
				}
			}
		}
		System.out.println(cnt);
	}
}

(12)P3799 妖梦拼木棒
用一个桶装下木棒的各个长度的个数。然后枚举两根短的木棒可以推出长的木棒。根据排列组合的知识可以算出每种长度的组合有多少种情况。

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;

public class Main {
	public static void main(String[] args) throws  IOException  {
		int mod=1000000007;
		BufferedReader br=new BufferedReader(new InputStreamReader(System.in));
		int n=Integer.valueOf(br.readLine());
		long[] arr=new long[5010];
		for(int i=1;i<=n;i++) {
			arr[Integer.valueOf(br.readLine())]++;
		}
		long sum=0;
		for(int i=1;i<5000;i++) {
			for(int j=i;j<=5000;j++) {
				if(i+j>5000)
					break;
				if(i==j) {
					if(arr[i]>=2&&arr[i<<1]>=2) {
						sum+=arr[i]*(arr[i]-1)%mod*arr[i+j]%mod*(arr[i+j]-1)/4;
						sum%=mod;
					}
				}
				else {
					if(arr[i]>=1&&arr[j]>=1&&arr[i+j]>=2) {
						sum+=(arr[i]*arr[j])%mod*(arr[i+j])%mod*(arr[i+j]-1)/2;
						sum%=mod;
					}
				}
			}
		}
		System.out.println(sum);	

	}
}

(13)P2392 kkksc03考前临时抱佛脚
一开始以为是贪心问题,看了题解才发现是01背包。价值和重量都是消耗的时间,而背包容量限制是t/2。然后用t-最大价值为一个科目耗的时间。

import java.util.Scanner;

public class Main{
	public static void main(String[] args) {
		Scanner sc=new Scanner(System.in);
		int[] a=new int[4];
		for(int i=0;i<4;i++) {
			a[i]=sc.nextInt();
		}
		int[][] dp=new int[21][1201];
		int all_t=0;
		int[] b=new int[21];
		for(int i=0;i<4;i++) {
			int t=0;
			for(int j=1;j<=a[i];j++) {
				b[j]=sc.nextInt();
				t+=b[j];
			}
			for(int x=1;x<=a[i];x++) {
				for(int y=1;y<=t/2;y++) {
					if(y>=b[x]) dp[x][y]=Math.max(dp[x-1][y-b[x]]+b[x], dp[x-1][y]);
					else dp[x][y]=dp[x-1][y];
				}
			}
			all_t+=t-dp[a[i]][t/2];
		}
		System.out.println(all_t);
	}
}

(14)P2036 Perket
一道简单的搜索题,因为数据量很小,所以我们可以直接搜索每一种情况。
最后把酸度相乘,甜度相加,然后酸度甜度绝对值差最小为结果。当然题目说了,不能一种都不选,那么要去掉一种都没有选的情况。

import java.util.Scanner;

public class Main {
	static int n;
	static int[] a1,a2;
	static int min=Integer.MAX_VALUE;
	public static void main(String[] args) {
		Scanner sc=new Scanner(System.in);
		n=sc.nextInt();
		a1=new int[n];
		a2=new int[n];
		for(int i=0;i<n;i++) {
			a1[i]=sc.nextInt();
			a2[i]=sc.nextInt();
		}
		dfs(0,1,0,false);
		System.out.println(min);
	}
	public static void dfs(int index,int sum1,int sum2,boolean flag) {
		if(index==n) {
			if(flag) {
			 min=Math.min(Math.abs(sum1-sum2), min);}
			 return;
		}
		dfs(index+1,sum1*a1[index],sum2+a2[index],true);
		dfs(index+1,sum1,sum2,flag);
	}
}

(15)P1433 吃奶酪
一道搜索题目,数据量不大,可以算出所有两点之间的距离。然后考虑每一种走的方案,维护一个最小值。

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;

public class Main {
	static double min=10000000;
	static double[][] arr;
	static int n;
	static boolean[] vis;
	public static void main(String[] args) throws  IOException {
		BufferedReader br=new BufferedReader(new InputStreamReader(System.in));
		n=Integer.valueOf(br.readLine());
		double[] a=new double[n+1];
		double[] b=new double[n+1];
		arr=new double[n+1][n+1];
		vis=new boolean[n+1];
		for(int i=1;i<=n;i++) {
			String[] s=br.readLine().split(" ");
			a[i]=Double.valueOf(s[0]);
			b[i]=Double.valueOf(s[1]);
		}
		for(int i=0;i<=n;i++) {
			for(int j=0;j<=n;j++) {
				arr[i][j]=Math.sqrt((a[i]-a[j])*(a[i]-a[j])+(b[i]-b[j])*(b[i]-b[j]));
			}
		}
		dfs(0,0,0);
		System.out.println(String.format("%.2f", min));
	}
	public static void dfs(int index,int now,double sum) {
		if(sum>min) {
			return;
		}
		if(now==n) {
			min=Math.min(sum, min);
			return;
		}
		for(int i=1;i<=n;i++) 
		      if(!vis[i])  
		        {
		            vis[i]=true;  
		            dfs(i,now+1,sum+arr[index][i]);  
		            vis[i]=false;  
		        }
		
	}
}
发布了26 篇原创文章 · 获赞 18 · 访问量 4626

猜你喜欢

转载自blog.csdn.net/qq_43751506/article/details/105004554
今日推荐