题目一:等边三角形
手上有一些小木棍,它们长短不一,想用这些木棍拼出一个等边三角形,并且每根木棍都要用到。 例如,手上有长度为 11,2,33,33 的4根木棍,他可以让长度为11,2 的木棍组成一条边,另外 222跟分别组成 222条边,拼成一个边长为 3 的等边三角形。
首先输入一个整数 n(3≤n≤20)表示木棍数量,接下来输入 n 根木棍的长度 pi(1≤pi≤10000);
能拼出来输出Yes,否则输出no
import java.util.Arrays;
import java.util.Scanner;
public class 等边三角形 {
static int flag = 0;
static int leng[];
static int singlength;
static boolean flagcon;
public static void main(String[] args) {
// TODO Auto-generated method stub
Scanner input = new Scanner(System.in);
int n = input.nextInt();
leng = new int[n];
boolean visit[] = new boolean[n];
int sum = 0;
for (int i = 0; i < leng.length; i++) {
leng[i] = input.nextInt();
sum+=leng[i];
}
if (sum%3==0) {//3的倍数才有可能拼成三角形
singlength = sum/3;
for (int i = 0; i < leng.length; i++) {
if (leng[i]>singlength) {
System.out.println("no");//有一条边太大,也凑不成三角形
}
}
}else {
System.out.println("no");
return;
}
Arrays.sort(leng);//长度排序
dfs(visit, 0);
if (flag==2) {//有两条边成功了,就拼成三角形
System.out.println("yes");
}else {
System.out.println("no");
}
}
/**
* @param visit 标记数组
* @param sticklength 已经拼凑的长度
*/
private static void dfs(boolean[] visit,int sticklength) {
// TODO Auto-generated method stub
if (flag==2) {
return;
}
if (sticklength==singlength) {
flagcon=true;//回溯的时候不要取消标记
flag++;
return;
}
if (sticklength>singlength) {
return;
}
for (int i = 0; i < leng.length; i++) {
if (visit[i]==false) {
if (sticklength+leng[i]<=singlength) {
visit[i]=true;
sticklength+=leng[i];
dfs(visit, sticklength);
if (flagcon==false) {//回溯
sticklength-=leng[i];
visit[i]=false;
}else {//flagcon=true,不取消标记
flagcon=false;
dfs(visit,0);//遍历第二个边
return;
}
}else {
break;//后面的棍子长度肯定大于singlength
}
}
}
}
}
题目二:
每个任务有一个所需的完成时间,现在需要将这些任务分配给一些人(每个人同时只能完成一个任务,每个任务都必须有人完成),使得每个人完成被分配的所有任务所需时间完全一样。你能算出最多能将这些任务分配给多少人么?
输入1:
27
10 7 9 10 13
23 2 3 31 1
5 6 7 8 9 6
6 5 4 1 2 3
3 11 13 12 6
输出1:6
输入:
9
5 2 1 5 2 1 5 2 1
输出4
import java.util.Arrays;
import java.util.Scanner;
public class 分配任务 {
static int a[];
static boolean flag;
public static void main(String[] args) {
// TODO Auto-generated method stub
Scanner input = new Scanner(System.in);
int n = input.nextInt();
// int n=27;
a = new int[n];
int sum = 0;
int maxsingtask = Integer.MIN_VALUE;
for (int i = 0; i < a.length; i++) {
a[i] = input.nextInt();
if (maxsingtask<a[i]) {
maxsingtask = a[i];//记录最大的单个任务量
}
sum += a[i];//记录总的任务量
}
Arrays.sort(a);//排序!!
int maxpeoplenum = sum/maxsingtask+1;//能保证每个任务完成的情况下的最大人数;
//遍历每一种分配方案
for (int i = maxpeoplenum; i > 0; i--) {//分配给i个人
if (sum%i==0) {//分配的尽的话
int singtask = sum/i;//每个人得到singtask的任务量
boolean visit[] = new boolean[n];
dfs(i,singtask,singtask,visit);
if (flag) {
System.out.println(i);//这次分配个i个人行得通。并且肯定是最大人数。结束
return;
}
}
}
System.out.println("end");
}
/**
* @param peoplenum 这次分配的人数
* @param inittasknum 分配的任务量-用来完成一个人初始化dfs的tasknum;
* @param tasknum 需要分配的任务量,tasknum=0则表示peoplenum个人的任务分配完毕
* @param visit 标记数组
*/
private static void dfs(int peoplenum, int inittasknum, int tasknum, boolean[] visit) {
// TODO Auto-generated method stub
if (peoplenum==0) {
flag=true;
return ;
}
for (int j = 0; j < a.length; j++) {
if (visit[j]==false) {
if (tasknum-a[j]>0) {//第peoplenum个人还没分配完
visit[j]=true;
tasknum -= a[j];
dfs(peoplenum, inittasknum, tasknum, visit);//
tasknum += a[j];//回溯
visit[j]=false;
}else if (tasknum-a[j]==0) {//分配完一个人的时候
visit[j]=true;
peoplenum--;
dfs(peoplenum, inittasknum, inittasknum, visit);//这次分配的visit需要保留不用回溯
}else {
/*这里有疑问。用Arrays.sort(a); a排列后,这里应该使用break;但是程序会一直跑,为什么??9个任务的能跑出来,27个任务的一直在跑;
* 去掉Arrays.sort(a); 后27个任务的一下就出来了。不懂为什么排序后 会一直跑*/
break;//减这个a[j]都不满足 ,减后面的更不满足;
// continue;
}
}
}
}
}