文章目录
P1563 [NOIP2016 提高组] 玩具谜题
题目描述
小南有一套可爱的玩具小人, 它们各有不同的职业。
有一天, 这些玩具小人把小南的眼镜藏了起来。 小南发现玩具小人们围成了一个圈,它们有的面朝圈内,有的面朝圈外。如下图:
这时singersinger告诉小南一个谜題: “眼镜藏在我左数第3个玩具小人的右数第11个玩具小人的左数第22个玩具小人那里。 ”
小南发现, 这个谜题中玩具小人的朝向非常关键, 因为朝内和朝外的玩具小人的左右方向是相反的: 面朝圈内的玩具小人, 它的左边是顺时针方向, 右边是逆时针方向; 而面向圈外的玩具小人, 它的左边是逆时针方向, 右边是顺时针方向。
有 n个玩具小人围成一圈, 已知它们的职业和朝向。现在第1个玩具小人告诉小南一个包含m条指令的谜題, 其中第 z条指令形如“左数/右数s个玩具小人”。 你需要输出依次数完这些指令后,到达的玩具小人的职业。
输入格式
输入的第一行包含两个正整数 n,m,表示玩具小人的个数和指令的条数。
接下来 n 行,每行包含一个整数和一个字符串,以逆时针为顺序给出每个玩具小人的朝向和职业。其中 0 表示朝向圈内,1 表示朝向圈外。 保证不会出现其他的数。字符串长度不超过 10 且仅由小写字母构成,字符串不为空,并且字符串两两不同。整数和字符串之间用一个空格隔开。
接下来 m 行,其中第 ii 行包含两个整数 a_i,s_i,表示第i 条指令。若 a_i=0,表示向左数 s_i个人;
若 a_i=1,表示向右数 s_i个人。
输出格式
输出一个字符串,表示从第一个读入的小人开始,依次数完 mm 条指令后到达的小人的职业。
输入输出样例
输入 #1复制
7 3
0 singer
0 reader
0 mengbier
1 thinker
1 archer
0 writer
1 mogician
0 3
1 1
0 2
输出 #1复制
writer
package 洛谷习题;
import java.util.Scanner;
public class P1563 {
static int m,n;
static int a[] = new int [101000];
static String s[] = new String [101000];
public static void main(String[] args) {
Scanner in = new Scanner(System.in);
m = in.nextInt();
n = in.nextInt();
for(int i=1;i<=m;i++) {
a[i] = in.nextInt();
s[i] = in.next();
}
int index = 1;
for(int i=0;i<n;i++)
{
int a1 = in.nextInt();
int b1= in.nextInt();
//退
if(a1==0&&a[index]==0) {
index -=b1;
if(index<1) {
index = -index;
index = index%m;
index = m-index;
}
}
else if(a1==1&&a[index]==1) {
index -=b1;
if(index<1) {
index = -index;
index = index%m;
index = m-index;
}
}
//进
else if(a1==1&&a[index]==1) {
index +=b1;
if(index>m)
index = index%m;
}
else{
index +=b1;
if(index>m)
index = index%m;
}
}
System.out.println(s[index]);
}
}
P1464 Function
解题思路:单纯递归肯定会超时,所以需要增加记忆化搜索,因为最大也就20,所以我们可以开一个三维数组,存放不同a,b,c时的值,并且设置一个布尔类型的数组,在递归的时候判断是否为真,如果是说明算过了,直接返回已经算过的数值。
package 洛谷习题;
import java.util.Scanner;
public class P1464 {
static int w(int a,int b,int c) {
if(a<=0 || b<=0 || c<=0)return 1;
else if(a>20 || b>20 || c>20)
return w(20,20,20);
if(v[a][b][c]) return k[a][b][c];
else if(a<b&&b<c)
k[a][b][c] = w(a,b,c-1)+w(a,b-1,c-1)-w(a,b-1,c);
else
k[a][b][c] = w((a-1),b,c)+w(a-1,b-1,c)+w(a-1,b,c-1)-w(a-1,b-1,c-1);
v[a][b][c] = true;
return k[a][b][c];
}
static int k[][][] = new int [21][21][21];
static boolean v[][][] = new boolean [21][21][21];
public static void main(String[] args) {
Scanner in = new Scanner (System.in);
boolean flag = true;
while(flag) {
int a1 = in.nextInt();
int b1 = in.nextInt();
int c1 = in.nextInt();
if(a1==-1&&b1==-1&&c1==-1)
flag = false;
else {
int ans = w(a1,b1,c1);
System.out.printf("w(%d, %d, %d) = %d\n",a1,b1,c1,ans);
}
}
}
}
P1803 凌乱的yyy / 线段覆盖
题目描述
现在各大 oj 上有 n 个比赛,每个比赛的开始、结束的时间点是知道的。
y 认为,参加越多的比赛,noip 就能考的越好(假的)。
所以,他想知道他最多能参加几个比赛。
由于 y 是蒟蒻,如果要参加一个比赛必须善始善终,而且不能同时参加 2 个及以上的比赛。
输入格式
第一行是一个整数 n ,接下来 n 行每行是 2 个整数 a_{i},b_{i}( a_{i}<b_{i} ),表示比赛开始、结束的时间。
输出格式
一个整数最多参加的比赛数目。
输入输出样例
输入 #1复制
3
0 2
2 4
1 3
输出 #1复制
2
解题思路:贪心先对数组按结束时间进行排序,然后从第一个开始往后遍历,如果上一个的结束时间小于下一个的开始时间,则计数器加一,同时标记新的结束时间与下一个对比。
import java.util.Arrays;
import java.util.Scanner;
public class P1803 {
static int n,ans,ens;
static class Game implements Comparable<Game>{
int start;
int end;
public Game(int start, int end) {
super();
this.start = start;
this.end = end;
}
public int compareTo(Game o) {
return this.end - o.end;
}
}
static Game[] game = new Game[1000000];
public static void main(String[] args) {
Scanner in = new Scanner (System.in);
n = in.nextInt();
for(int i=0;i<n;i++) {
int a = in.nextInt();
int b = in.nextInt();
game[i] = new Game(a, b);
}
Arrays.sort(game,0,n);
int startTime = game[0].start; 第一个肯定有,直接标记
for(int i=0;i<n;i++) {
if(startTime<=game[i].start) {
ans++;
startTime = game[i].end;
}
}
System.out.println(ans);
}
}
P1540 [NOIP2010 提高组] 机器翻译
假设内存中有 M 个单元,每单元能存放一个单词和译义。每当软件将一个新单词存入内存前,如果当前内存中已存入的单词数不超过 M-1,软件会将新单词存入一个未使用的内存单元;若内存中已存入 M 个单词,软件会清空最早进入内存的那个单词,腾出单元来,存放新单词。
假设一篇英语文章的长度为 N 个单词。给定这篇待译文章,翻译软件需要去外存查找多少次词典?假设在翻译开始前,内存中没有任何单词。
输入格式
共 2 行。每行中两个数之间用一个空格隔开。
第一行为两个正整数 M,N,代表内存容量和文章的长度。
第二行为 N 个非负整数,按照文章的顺序,每个数(大小不超过 1000)代表一个英文单词。文章中两个单词是同一个单词,当且仅当它们对应的非负整数相同。
输出格式
一个整数,为软件需要查词典的次数。
输入输出样例
输入 #1复制
3 7
1 2 1 5 4 4 1
输出 #1复制
5
解题思路:先进去的先出来,赤裸裸的队列,先回去看了看自己写过的队列解题,这里列出队列的一些操作:
创建队列:
static Queue q = (Queue) new LinkedList();
获取队列的首位置值:q.peek();
加入队尾:q.offer(e);
移除队首:q.poll();
解题思路:每次读入一个数则对这个数判断是否为true,如果真则说明直接跳过。不为真则需要先判断是否队满,队满的话就需要移除队首,同时把队首的值对应的数组值变为false,之后就是进队尾操作,同时对这个数的数组值标记为true。
package 洛谷习题;
import java.util.ArrayList;
import java.util.LinkedList;
import java.util.Queue;
import java.util.Scanner;
public class P1540 {
static int m,n,ans;
static boolean a[] = new boolean [1010];
static Queue q = (Queue) new LinkedList();
public static void main(String[] args) {
Scanner in = new Scanner (System.in);
m = in.nextInt();
n = in.nextInt();
for(int i=0;i<n;i++) {
int j = in.nextInt();
if(a[j]) continue;
if(q.size()==m) {
a[(int)q.peek()] = false;
q.poll();
}
ans++;
q.offer(j);
a[j] = true;
}
System.out.println(ans);
}
}
P1206 [USACO1.2]回文平方数 Palindromic Squares
题目描述
回文数是指从左向右念和从右向左念都一样的数。如 12321 就是一个典型的回文数。
给定一个用十进制表示的正整数 BB,输出所有 [1,300]中,它的平方用 B 进制表示时是回文数的数。
输入格式
共一行,一个单独的正整数 B。
输出格式
每行两个 B 进制的符合要求的数字,第二个数是第一个数的平方,且第二个数是回文数。
注意大于 9 的数,用字母表示。如用 A 表示 10,B 表示 11,用第 n 个大写字母表示 n+9。
输入输出样例
输入 #1复制
10
输出 #1复制
1 1
2 4
3 9
11 121
22 484
26 676
101 10201
111 12321
121 14641
202 40804
212 44944
264 69696
解题思路:设置一个进制转化的函数,还有一个回文数的判断函数即可
import java.util.Scanner;
public class Main {
public static boolean HuiWen(StringBuffer x) {
for(int i=0;i<x.length()/2;i++) {
if(x.charAt(i)!=x.charAt(x.length()-i-1))
return false;
}
return true;
}
public static StringBuffer Zhuan(int num,int B) {
StringBuffer s = new StringBuffer();
int digit;
while(num>0) {
digit=num%B;
if(digit>=10) {
s.append((char)('A'+digit-10));
}
else {
s.append(digit);
}
num/=B;
}
return s.reverse();
}
public static void main(String[] args) {
Scanner in = new Scanner (System.in);
int n = in.nextInt();
for(int i=1;i<300;i++) {
StringBuffer s1 = Zhuan(i,n);
StringBuffer s2 = Zhuan(i*i,n);
if(HuiWen(s2))
System.out.println(s1 +" "+s2);
}
}
}
试题 H: 走方格
问题:
在平面上有一些二维的点阵。这些点的编号就像二维数组的编号一样,从上到下依次为第 1 至第 n 行,从左到右依次为第 1 至第 m 列,每一个点可以用行号和列号来表示。现在有个人站在第 1 行第 1 列,要走到第 n 行第 m 列。只能向右或者向下走。
注意,如果行号和列数都是偶数,不能走入这一格中。问有多少种方案。
输入:
输入一行包含两个整数 n, m。
输出:
输出一个整数,表示答案。
样例输入1:
3 4
样例输出1:
2
样例输入2:
6 6
样例输出2:
0
package text1;
import java.util.Scanner;
public class dfs {
static int n,m;
static int ans;
static int a[][] = new int [100][100];
static int v[][] = new int [100][100];
static int dx[] = {0,1};
static int dy[] = {1,0};
public static void dfs(int x,int y) {
if(x==n&&y==m) {
ans++;
return;
}
for(int i=0;i<2;i++) {
int tx = x+dx[i];
int ty = y+dy[i];
if(tx>=1&&tx<=n&&ty>=1&&ty<=m&&v[tx][ty]==0)
{
if(!((tx&1)==0&&(ty&1)==0))
{
v[tx][ty] = 1;
dfs(tx,ty);
v[tx][ty] = 0;
}
}
}
}
public static void main(String[] args) {
Scanner in = new Scanner (System.in);
n = in.nextInt();
m = in.nextInt();
if(!((n&1)==0&&(m&1)==0)) {
dfs(1,1);
System.out.println(ans);
}
else System.out.println("0");
}
}