文章目錄
T1 瑞神的序列
瑞神的數學一向是最好的,連強大的咕咕東都要拜倒在瑞神的數學水平之下,雖然咕咕東很苦惱,但是咕咕東拿瑞神一點辦法都沒有。 5.1期間大家都出去玩了,只有瑞神還在孜孜不倦的學習,瑞神想到了一個序列,這個序列長度爲 n,也就是一共有 n個數,瑞神給自己出了一個問題:數列有幾段? 段的定義是連續的相同的最長整數序列。
輸入
輸入第一行一個整數n,表示數的個數。
接下來一行n個空格隔開的整數,表示不同的數字。
輸出
輸出一行,這個序列有多少段 。
樣例輸入
12
2 3 3 6 6 6 1 1 4 5 1 4
樣例輸出
8
思路
綜述
題目是要求解一組數中,有幾個段,對於某一段,必須連續且數值相等;
比較簡單,用O(n)複雜度,掃一遍就可以;
想到另一個思路,(非本代碼思路)
倒着從後往前掃描;
如果後一個變量和前面的不一樣則總段數就++;最後再++;
點
想到一個點,如果輸入的數據爲0個,那就輸出0,不知道有沒有這樣的數據,反正檢驗一下不會錯。
代碼
#include <iostream>
using namespace std;
int n;
int a[1050];
int main(){
cin>>n;
int term;
int cnt = 0 ;
for(int i=0;i<n;i++){
cin>>a[i];
}
if(n==0)cout<<cnt<<endl;
else{
term = a[0];
cnt++;
for(int i=1;i<n;i++){
if(a[i]==term)continue;
else{
term = a[i];
cnt++;
}
}
cout<<cnt<<endl;
}
}
T2 消消樂大師——Q老師
Q老師是個很老實的老師,最近在積極準備考研。Q老師平時只喜歡用Linux系統,所以Q老師的電 腦上沒什麼娛樂的遊戲,所以Q老師平時除了玩Linux上的賽車遊戲SuperTuxKart之外,就是喜歡消消樂了。 遊戲在一個包含有 n 行 m 列的棋盤上進行,棋盤的每個格子都有一種顏色的棋子。當一行或一列 上有連續三個或更多的相同顏色的棋子時,這些棋子都被消除。當有多處可以被消除時,這些地方的棋子將同時被消除。 一個棋子可能在某一行和某一列同時被消除。 由於這個遊戲是闖關制,而且有時間限制,當Q老師打開下一關時,Q老師的好哥們叫Q老師去爬泰山去了,Q老師不想輸在這一關,所以它來求助你了!!
輸入
輸入第一行包含兩個整數n,m,表示行數和列數 ,接下來n行m列,每行中數字用空格隔開,每個數字代表這個位置的棋子的顏色。數字都大於0。
輸出
輸出n行m列,每行中數字用空格隔開,輸出消除之後的棋盤。(如果一個方格中的棋子被消除, 則對應的方格輸出0,否則輸出棋子的顏色編號。)
樣例輸入
4 5
2 2 3 1 2
3 4 5 1 4
2 3 2 1 3
2 2 2 4 4
樣例輸出
2 2 3 0 2
3 4 5 0 4
2 3 2 0 3
0 0 0 4 4
思路
哎,這個題做的真狼狽。最後輸出的時候,每一行最後沒有刪除空格,直接爆零;
綜述
定義兩個二維數組,
a用於存儲原始數據;
b數組用於存儲某個位置是否被消除。
由於數據量不大,所以針對每一個(i,j)位置的數;
往四個方向(上下左右)分別走一遍。
to_up(i,j);
to_down(i,j);
to_left(i,j);
to_right(i,j);
對某一個方向
以向右爲例;
記錄加上位置開始向右連續的有幾個相同的數共cnt個;
如果cnt>=3則b數組對應的位置標記一下,代表刪除;
void to_right(int i,int j){
int x = i;
int y = j;
int term = a[i][j];
int cnt = 1;
while(1){
y++;
if(y>m)break;
if(a[x][y]==term)cnt++;
if(a[x][y]!=term)break;
}
if(cnt>=3){
for(int y = j;y < m; y++){
b[x][y] = 0;
cnt--;
if(cnt==0)break;
}
}
}
總結:
四個方向其實不用寫四個函數,寫一個循環即可,但是上下和左右的判斷邏輯可能會出現想不到的BUG,於是爲了保險起見就寫了四個,其實單單就正確率和時間上來看,寫四個其實是最有利於這次測試,但是並不利於邏輯的訓練;
點
因爲可能有的地方,比如十字交叉的位置,如果單單用一個二維數組可能比較難處理,所以乾脆就設置兩個二維數組,如果多次對某一位置進行消除則,效果是一樣的。
代碼
#include <iostream>
using namespace std;
int n,m;
int a[35][35];
int b[35][35];
void to_up(int i,int j){
int x = i;
int y = j;
int term = a[i][j];
int cnt = 1;
while(1){
x--;
if(x<0)break;
if(a[x][y]==term)cnt++;
if(a[x][y]!=term)break;
}
if(cnt>=3){
for(int x = i; x >= 0; x--){
b[x][y] = 0;
cnt--;
if(cnt==0)break;
}
}
}
void to_down(int i,int j){
int x = i;
int y = j;
int term = a[i][j];
int cnt = 1;
while(1){
x++;
if(x>n)break;
if(a[x][y]==term)cnt++;
if(a[x][y]!=term)break;
}
if(cnt>=3){
for(int x = i;x < n; x++){
b[x][y] = 0;
cnt--;
if(cnt==0)break;
}
}
}
void to_left(int i,int j){
int x = i;
int y = j;
int term = a[i][j];
int cnt = 1;
while(1){
y--;
if(y<0)break;
if(a[x][y]==term)cnt++;
if(a[x][y]!=term)break;
}
if(cnt>=3){
for(int y = j;y < 0; y--){
b[x][y] = 0;
cnt--;
if(cnt==0)break;
}
}
}
void to_right(int i,int j){
int x = i;
int y = j;
int term = a[i][j];
int cnt = 1;
while(1){
y++;
if(y>m)break;
if(a[x][y]==term)cnt++;
if(a[x][y]!=term)break;
}
if(cnt>=3){
for(int y = j;y < m; y++){
b[x][y] = 0;
cnt--;
if(cnt==0)break;
}
}
}
int main(){
cin>>n>>m;
for(int i=0;i<n;i++){
for(int j=0;j<m;j++){
cin>>a[i][j];
b[i][j]=a[i][j];
}
}
for(int i=0;i<n;i++){
for(int j=0;j<m;j++){
to_up(i,j);
to_down(i,j);
to_left(i,j);
to_right(i,j);
}
}
for(int i=0;i<n;i++){
for(int j=0;j<m;j++){
if(j==0)cout<<b[i][j];
else cout<<" "<<b[i][j];
}
cout<<endl;
}
}
T4 咕咕東學英語
咕咕東很聰明,但他最近不幸被來自宇宙的宇宙射線擊中,遭到了降智打擊,他的英語水平被歸 零了!這一切的始作俑者宇宙狗卻毫不知情! 此時咕咕東碰到了一個好心人——TT,TT在吸貓之餘教咕咕東學英語。今天TT打算教咕咕東字母A 和字母B,TT給了咕咕東一個只有大寫A、B組成的序列,讓咕咕東分辨這些字母。 但是咕咕東的其他學科水平都還在,敏銳的咕咕東想出一個問題考考TT:咕咕東問TT這個字符串 有多少個子串是Delicious的。 TT雖然會做這個問題,但是他吸完貓發現輝夜大小姐更新了,不想回答這個問題,並拋給了你, 你能幫他解決這個問題嗎?
Delicious定義:對於一個字符串,我們認爲它是Delicious的當且僅當它的每一個字符都屬於一個大於1的迴文子串中。
輸入
輸入第一行一個正整數n,表示字符串長度, 接下來一行,一個長度爲n,只由大寫字母A、B構成的字符串。
輸出
輸出僅一行,表示符合題目要求的子串的個數。
樣例輸入
5
AABBB
樣例輸出
6
樣例解釋:
對於該樣例,符合條件的六個子串分別是:
s1-s4 AABB
s1-s5 AABBB
s3-s4 BB
s3-s5 BBB
s4-s5 BB
思路
以前做這種題都是順着推,這道題倒是給提醒了一個別具一格的思路–>求補集;
綜述
這道題剛剛開始做的時候,一門心思地想着如何去列出所有的情況,然後逐一擊破。但是沒想到的是求補集,也就是不行的情況更簡單;
滿足以下條件的就是不行的:
- A後面跟着若干個B
- B後面跟着若干個A
- 若干個A後面一個B
- 若干個B後面一個A
然後呢,求出所有子串的數量,然後減去上面提到的不滿足情況的就可以了;
注意
AB和BA可能會被計算兩次,注意減去一次
代碼
#include<iostream>
#include<vector>
#include<cstring>
#include<string.h>
#include<string>
using namespace std;
struct node{
char ch;
long long num;
node(){
num=0;
}
};
long long n;
string s;
vector<node> v;
int main(){
cin>>n>>s;
char c;
int number=0;
for(int i=0;i<s.size();i++){
if(i==0){
c = s[i];
number=1;
}
else if(s[i]==c){
number++;
}else{
node newnode;
newnode.ch = c;
newnode.num = number;
v.push_back(newnode);
c = s[i];
number = 1;
}
}
node newnode;
newnode.ch = c;
newnode.num = number;
v.push_back(newnode);
long long ans = (n-1)*n/2;
if(v.size()==1)cout<<ans<<endl;
else{
for(int i=0;i<v.size();i++){
if(i==0 || i==v.size()-1){
ans-=v[i].num;
continue;
}
ans-=v[i].num*2;
}
ans+=v.size()-1;
cout<<ans<<endl;
}
}