1. 程式人生 > >Luogu P1311 選擇客棧

Luogu P1311 選擇客棧

ios 循環 兩個 pac class bool isp display 所有

暴力

我一開始做這道題先想到的就是暴力。。。

所以先說一下暴力的做法。首先在輸入的時候講花費小於P的位置標記下來,然後用兩層循環枚舉所有的兩個客棧的組合方案。再用一層循環將兩個客棧之間的位置掃一遍,如果有被標記過得位置證明這種方案是可行的。將其統計下來。

暴力的代碼

技術分享圖片
#include <iostream>
#include <cstring>
#include <cstdio>
#include <cstring>

const int maxn = 2e5+3;
const int maxk = 53;

using namespace std; int x, f; char c; inline int read() { x = 0, f = 1; c = getchar(); while (c < 0 || c > 9) { if(c == -) f = -1; c = getchar(); } while (c <= 9 && c >= 0) { x = x*10 + c-0; c = getchar(); }
return x * f; } int n, k, p, col[maxn], cost[maxn], Ans; bool book[1003][1003]; int main() { n = read(), k = read(), p = read(); for(int i=1; i<=n; i++) { col[i] = read(); cost[i] = read(); } for(int i=1; i<=n; i++) { for(int j=i+1; j<=n; j++) {
for(int k=i; k<=j; k++) { if(cost[k] <= p) { book[i][j] = true; } } } } for(int i=1; i<=n; i++) { for(int j=i+1; j<=n; j++) { if(book[i][j] == true && col[i] == col[j]) { Ans++; } } } printf("%d", Ans); }
暴力

正解

我們邊輸入邊做處理,考慮用一個cnt[i]表示顏色為i的客棧在當前位置之前有多少個同樣顏色的客棧。用一個now表示最後一家花費小於等於P的咖啡店的位置。再用一個last[i]表示最後一家顏色為i的客棧的位置。顯然,如果last[i]小於等於now,那就說明當前位置上的客棧可以和之前的所有顏色為i的客棧組合,否則就繼續往後掃。重復這些操作,沿途統計有多少種組合

正解的代碼

#include <cstdio>

const int maxk = 53;

using namespace std;

int x, f; char c;

inline int read() {
    x = 0, f = 1;
    c = getchar();
    while (c < 0 || c > 9) {
        if(c == -) f = -1;
        c = getchar();
    }
    while (c <= 9 && c >= 0) {
        x = x*10 + c-0;
        c = getchar();
    }
    return x * f;
}

int n, k, p, now, color, cost, Ans, cnt[maxk], sum[maxk], last[maxk];

int main() {
    n = read(), k = read(), p = read();
    for(int i=1; i<=n; i++) {
        color = read();
        cost = read();
        if(cost <= p)
            now = i;
        if(now >= last[color])
            sum[color] = cnt[color];
        Ans += sum[color];
        last[color] = i;
        cnt[color]++;
    }
    printf("%d", Ans);
}

Luogu P1311 選擇客棧