コンテンツ
1.トピックの説明:
機関はチケットコンテストを主催します。勝者はいくつかのチケットを獲得するチャンスがあります。
ホストはN枚のカード(1〜Nの数字が書かれている)を取り出し、シャッフルして輪に並べます。あなたはどれからでも選ぶことができます
カードは時計回りにカウントを開始します:1,2,3 .....番号がカードの番号とまったく同じである場合は、カードをポケットに入れます
、次のカードからもう一度数えます。カードを収穫できなくなるまで、ゲームは終了します。バッグの中のカード番号の合計が勝ちです
チケットの数。
例:
カードの配置は次のとおりです。1 2 3
1枚目のカードから数え始め、1枚目のカードを取り出します。もう一度カード番号2から始めますが、番号がカードと一致することができず、番号はまもなく
どんどん大きくなっていくと、もうカードを奪うことはできません。そのため、今回は1枚のチケットしか獲得できませんでした。悪くない!始めたら
カード2または3から数えると、愚かなことに、1枚のカードを手に入れることはできません。
運が良ければ、カードの配置は213です。
そうすれば、すべてのカードをスムーズに入手できます!
この問題の目的は、カードの時計回りのシーケンスを知ることです。
カウントを開始する場所で、獲得できるチケットの最大数(ポケットにあるカードの数の合計)を見つけます。
入力フォーマット
最初の行には、カードの数を示す整数N(N <100)が
含まれています。2番目の行には、時計回りに配置されたカードを示すN個の整数が含まれています。
出力フォーマット
最良の場合に獲得できるチケットの数を示す1行の整数
ユーザー入力:
3
1 2 3
プログラムは次のように出力する必要があります:
1
ユーザー入力:
3
2 1 3
プログラムは次のように出力する必要があります:
6
2.問題分析
タイトルにはたくさんのテキストの説明があります。簡単な分析と要約の下で、1-Nから数字を選択して、1から時計回りにカウントを開始します。カウント値が
カードの値、つまり1-Nの値と等しい場合は、カードを取り出し(カードの値を取得)、次のカードから開始します。
もう一度1から数えて、カードの最大値を尋ね、
1.質問の意味によると、私たちが最初に考えることは、考えられるすべての状況を列挙し、最大値を見つけることです。これはまさにこの質問の問題解決のアイデアです
道。実際、ブルーブリッジカップによって列挙されたトピックはしばしば調べられます。列挙のアイデアを明確に使用した後、重要なのは、どのように列挙するか、そしてどのように列挙するかです。
時間の詳細。
2.最初のカードから列挙を開始し、カウントを続行します。カウントがカードの値と等しい場合は、カードの値を加算します。
(カウントの値の場合もあります)、問題は、このカードを取得するための条件が満たされている場合、列挙を続行するときにこのカードをスキップする必要があることです。
カード、カードが取り外されたことをどうやって知ることができますか?
3.変数を使用してマークを付けることができますが、複数のカードの場合、マークを付けるには複数の変数が必要です。
アレイの使用に関しては、マーキングのために新しいアレイを再度開くことができます。または、カードが取り外されている場合は、カードの位置を記録するアレイを使用できます。
スライスの場合、この位置の値は-1に設定されるため、列挙中に-1が検出された場合は、直接スキップされます。
4.配列が使用されている場合、カウントが終了した後、特定のカードから列挙し、次に開くカードを列挙し続けます
このとき、前回処理した配列が絶対に使えない場合は、毎回開始配列を列挙する必要があります。
カードは、最初に入力されたカードの順序に等しい一時的な配列を再利用しようとしています
5.各列挙は、変数sumを使用して今回取得した値を記録し、この列挙が終了したら、maxを更新して最大値を記録します。
3.コードの実装
Javaコードの実装
import java.util.Scanner;
class Main{
//定义全局数组nums 和 数组长度 n 方便函数调用
static int[] nums;
static int n;
public static void main(String[] args) {
Scanner sc = new Scanner(System.in);
n = sc.nextInt();
nums = new int[n];
for(int i = 0;i <n;i++) {
nums[i] = sc.nextInt();
}
System.out.println(getMax());
}
static int getMax() {
int max = 0;
for(int i = 0;i < n;i++) {
//每次重新选择一行牌作为起始 都要重新设置临时数组
int[] temp = new int[n];
//初始化临时数组
for(int k = 0;k < n;k++) {
temp[k] = nums[k];
}
//计数
int count = 1;
//记录一次枚举获得的卡片数值和
int sum = 0;
// 标记是否count大于所有剩余卡片数值,如果true即已经不能再取卡片的跳出循环进行下一
// 次枚举
boolean flag = true;
// 开始计数的卡片对应的位置下标
int start = i;
while(true) {
// 每次循环重置flag标识
flag = true;
//判断是否有剩余卡片的数值大于count,如果没有那么不会再取卡片直接跳出循环
for(int k = 0;k < n; k++) {
if(temp[k] >= count) {
flag = false;
break;
}
}
//如果count大于所有数组中的数,那么不能继续数下去了
if(flag) break;
int j = start ;
//如果计数count 等于 卡片的数值 temp[j]
if(count == temp[j]) {
sum += count;
temp[j] = -1;
count = 1;
}else {
//计数count 不等于 卡片的数值 count+1
count++;
}
//不管是否取走卡片都要继续进行顺时针的下一张卡片
start = (start+1) % n;
//num用来记录此时已经取走的卡片数量,防止全部取走后 一直进行while循环
int num = 0;
//跳过已经取走的卡片
while(temp[start] == -1) {
start = (start+1) % n;
num++;
//防止死循环
if(num > n ) break;
}
}
//每次枚举一张卡片开始就更新下 max值
max = Math.max(max, sum);
}
return max;
}
}
注意点:
1. Javaを使用していて、パッケージをインポートする必要があります。インポートするパッケージがわからない場合、またはインポートするパッケージが多い場合は、直接インポートできます。
import java.util.*;
utilパッケージの下にあるすべてのサブパッケージを示し、2番目のクラスはクラスMainという名前にする必要があります
2.ループ内のカードを選択するときは、配列の添え字が範囲外にならないように、 nの余りを取ることを忘れないでください。
3.各カウントの開始時にフラグをtrueにリセットする必要があります(残りのカードの値がカウントよりも大きいかどうかを判断するため、そうでない場合は、テーブル
カウントがすべてのカードの値よりも大きいことを示します。これ以上等しいものはなく、カードはそれ以上取られず、ループは直接飛び出します)前のループを防ぎます
結果は次のサイクルに影響を与え、無限ループを引き起こします
4.取り出されたカードをスキップする場合は、この時点で取り出されたカードの数を記録するために変数numを設定する必要があります。
それを取り出してループから飛び出し、無限ループを防ぎます
ブルーブリッジカップ大会が始まるまでまだ1ヶ月あります。賞品を獲得し、学校に登録料を返済させるために、私は本当の質問を一生懸命練習し始めました。xdm、go go go go !!!