POJ练习1

POJ2000 Gold Coins

  1. 题目:Gold Coins
  2. 题解:如果只开一个数组存每天获得的金币的话,一共要存(10000*10001)/2这么多的数,显然不太理想,可以转化为一共10000轮,每轮送N天每天N个,保存每轮的终点,另开一个数组保存从开始到该轮结束的金币总数
package 蓝桥;

import java.util.Scanner;

public class Main {
	public static void main(String[] args) {
		int[] num=new int[10001];//下标表示该轮连送N天每次N个,值表示这一轮最后一天
		int[] coin=new int[10001];//每轮送完共送多少个
		for(int i=1;i<10001;i++) {
		//0 1 3 6 10,即第一轮到第一天每次一个,第二轮到第三天每次两个……
			num[i]=i+num[i-1];
		//连送i天每次i个加上上一轮送的
			coin[i]=i*i+coin[i-1];
		}
		Scanner sc=new Scanner(System.in);
		while(sc.hasNext()) {
			int n=sc.nextInt();
			if(n==0) return;
			for(int i=1;i<10001;i++) {
				if(n<=num[i]) {//在这一轮内
					int gold=coin[i]-(num[i]-n)*i;//离送完那天差几天就减掉几天的
					System.out.println(n+" "+gold);//按格式输出
					break;
				}
			}
		}
	}
}

POJ2001 Shortest Prefixes

  1. 题目: Shortest Prefixes

  2. 题解
    2.1:暴力枚举每个单词所有前缀验证可行性

package 蓝桥;

public class Main {
	static String[] str=new String[1001];
	static String[] pre=new String[1001];
	public static void main(String[] args) {
		Scanner sc=new Scanner(System.in);
		int i=0;
		while(sc.hasNext()) {
			str[i]=sc.next();
			//自己测试数据结尾要输入Ctrl+Z表示输入结束
			i++;
		}
		for(i=0;str[i]!=null;i++) {//获取每个单词的最短前缀
			if(pre[i]==null)
				getpre(str[i],i);
		}
		for(i=0;pre[i]!=null;i++) {//按格式输出
			System.out.println(str[i]+" "+pre[i]);
		}
	}
	static void getpre(String s,int n) {
			for(int end=1;end<s.length()+1;end++ ) {
				String sPre=s.substring(0, end);
				//枚举所有前缀
				if(cheak(sPre,end,n)) {//可行,求下一个单词
					pre[n]=sPre;
					return;
				}
				if(end==s.length()) {//如果除了他本身以外的前缀都不能用,那本身就是最短前缀
					pre[n]=sPre;
				}
			
		}
	}
	private static boolean cheak(String sPre, int end,int n) {
		
		for(int i=0;str[i]!=null;i++) {//遍历所有单词
			if(i==n) continue;//不求本身
			if(end>str[i].length()) {//该单词长度比所求前缀短,目前可行,求下一单词
				continue;
			}
			if(sPre.equals(str[i])) {
			//该单词和该前缀完全相同,则该单词的前缀就是他本身,且该前缀不可行
				pre[i]=str[i];
				return false;
			}
			
			String s=str[i].substring(0, end);
			
			if(sPre.equals(s)) {//该单词有相同的前缀,不可行
				return false;
			}
		}
		return true;
	}
}

2.2:字典树

package 蓝桥;

import java.util.LinkedList;
import java.util.Queue;
import java.util.Scanner;

public class Main {

	public static void main(String[] args) {
		Scanner sc = new Scanner(System.in);
		Trie trie = new Trie();
		Queue<String> queue = new LinkedList<String>();
		while (sc.hasNext()) {
			String word = sc.nextLine();
			queue.offer(word);
			trie.insert(word);
		}
		while (!queue.isEmpty()) {
			String word = queue.poll();
			System.out.println(word + " " + trie.search(word));
		}
		sc.close();
	}

}

class Trie {

	private Node root;

	public Trie() {
		root = new Node(new Node[26], 0);
	}

	public void insert(String word) {
		Node current = root;
		for (int i = 0; i < word.length(); ++i) {
			if (null != current.getSon(word.charAt(i) - 'a')) {
				current = current.getSon(word.charAt(i) - 'a');
				current.setCount(current.getCount() + 1);
			} else {
				Node newNode = new Node(new Node[26], 1);
				current.setSon(word.charAt(i) - 'a', newNode);
				current = newNode;
			}
		}
	}

	public String search(String word) {
		Node current = root;
		StringBuilder prefix = new StringBuilder();
		for (int i = 0; i < word.length(); ++i) {
			if (1 == current.getCount()) {
				break;
			}
			prefix.append(word.charAt(i));
			current = current.getSon(word.charAt(i) - 'a');
		}
		if (1 == current.getCount()) {
			return prefix.toString();
		} else {
			return word;
		}
	}

}

class Node {

	private Node[] son;
	private int count;

	public Node(Node[] son, int count) {
		this.son = son;
		this.count = count;
	}

	public Node getSon(int i) {
		return son[i];
	}

	public void setSon(int i, Node node) {
		son[i] = node;
	}

	public int getCount() {
		return count;
	}

	public void setCount(int count) {
		this.count = count;
	}

}

POJ2005 Blackjack

  1. 题目:Blackjack
  2. 题解:因为A的大小由执牌者决定,而除非两张A不然不会爆点,所以A总是11.
package 蓝桥;

import java.util.Scanner;

public class Main {

	public static void main(String[] args) {
		String[] card; // 存储输入数据
		int[] poker;//手牌
		int[] num;//每张牌出现次数
		int player, dealer;//玩家手牌的点数,庄家手牌点数
		double count;//现有牌数
		int sum;//玩家能赢的所有情况
		Scanner sc = new Scanner(System.in);
		while (sc.hasNext()) {
			int n = sc.nextInt();
			if (n == 0)
				return;
			card = new String[3];
			num = new int[14];
			poker = new int[3];
			for (int i = 0; i < 3; i++) {
				card[i] = sc.next();
				poker[i] = change(card[i]);
				num[poker[i]]++;
			}
			count = n * 52 - 3;
			player = poker[1] + poker[2];
			if (player == 22) {
				player = 12;
			}
			dealer = poker[0];
			sum = 0;
			for (int i = 2; i <= 11; i++) {
				if (((dealer + i == 22) ? 12 : dealer + i) < player) {

					if (i == 10)
						sum += n * 4 * 4 - num[i]; //TJQK 四个10。
					else
						sum += n * 4 - num[i]; // 如果出现过,就要减去
				}
			}
			System.out.printf("%.3f%%\n\n", sum * 100 / count);//注意输出格式
		}

	}

	static int change(String num) {
		char ch = num.charAt(0);
		if (ch == 'A')
			return 11;
		else if (ch == 'T' || ch == 'J' || ch == 'Q' || ch == 'K')
			return 10;
		else
			return ch - '0';
	}
}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值