AOJ0033 Ball【贪心+序列处理】
図のように二股に分かれている容器があります。1 から 10 までの番号が付けられた10 個の玉を容器の開口部 A から落とし、左の筒 B か右の筒 C に玉を入れます。板 D は支点 E を中心に左右に回転できるので、板 D を動かすことで筒 B と筒 C のどちらに入れるか決めることができます。
開口部 A から落とす玉の並びを与えます。それらを順番に筒 B 又は筒 Cに入れていきます。このとき、筒 B と筒 C のおのおのが両方とも番号の小さい玉の上に大きい玉を並べられる場合は YES、並べられない場合は NO と出力するプログラムを作成してください。ただし、容器の中で玉の順序を入れ替えることはできないものとします。また、続けて同じ筒に入れることができるものとし、筒 B, C ともに 10 個の玉がすべて入るだけの余裕があるものとします。
Input
複数のデータセットが与えられます。1行目にデータセット数 N が与えられます。つづいて、N 行のデータセットが与えられます。各データセットに 10 個の番号が左から順番に空白区切りで与えられます。
Output
各データセットに対して、YES または NO を1行に出力して下さい。
Sample Input
2 3 1 4 2 5 6 7 8 9 10 10 9 8 7 6 5 4 3 2 1
Output for the Sample Input
YES NO
问题链接:AOJ0033 Ball
题意简述:如图,有从中间分为两股的容器,编号为1-10的球从开口的A落下,可以控制板子D,使得球进入B或C筒。落入筒B或C中的球,必须保证大号的在上,小号的在下。B和C筒都有装10个球的空间。问能否按照要求将球装入筒中。
输入有多个用例。第一行是数据用例数n,后面n行的每一行是10个1-10的球号,用空格隔开。
对于每一个输入用例,输出一行YES或NO。
问题分析:
原书作者将此题归于DFS,实际上没有必要,顺序处理各个球就可以了。
筒B和C似乎像堆栈,其实没有必要使用堆栈。因为最后结果只需要判定YES或NO,只要知道用筒顶端的球号即可。
之所以把这个题归为贪心,在于处理原则。一个球来了,尽可能放在大号的球上即可(总是先试探B筒,再试探C筒)。
程序说明:
顺序处理的最大好处是把数据看一遍就好了,还不需要使用数组,省空间。
当得到结论时,计算判断处理是不需要了,但是还需要把一组数据全部读入。
题记:(略)
AC的C++程序如下:
/* AOJ0033 Ball */ #include <iostream> using namespace std; const int N = 10; int main() { int n; cin >> n; while(n--) { bool ans = true; int a, b=-1, c=-1; for(int i=1; i<=N; i++) { cin >> a; if(ans) { if(a > b) b = a; else if(a > c) c = a; else ans = false; } } cout << (ans ? "YES" : "NO") << endl; } return 0; }
AC的C语言程序如下:
/* AOJ0033 Ball */ #include <stdio.h> #define N 10 int main(void) { int n, ans, i; scanf("%d", &n); while(n--) { ans = 1; int a, b=-1, c=-1; for(i=1; i<=N; i++) { scanf("%d", &a); if(ans) { if(a > b) b = a; else if(a > c) c = a; else ans = 0; } } printf("%s\n", ans ? "YES" : "NO"); } return 0; }