2024年5月21日

liuyichen發表於2024-05-21

A luoguP3030

考慮DP

狀態 (i, sum, data)表示已經放了 \(i\) 個磚塊, 總和為 \(sum\) 是的最小花錢。

轉移 : 列舉第 \(i\) 個選多少。

時間複雜度 \(O(n\sqrt{m} \cdot m)\)

#include<bits/stdc++.h>

using namespace std;

const int N = 15, M = 10005;
const long long INF = 1e18;

int n, m, a[N];
long long dp[N][M];

int main(){
  freopen("tilechng.in", "r", stdin);
  freopen("tilechng.out", "w", stdout);
  cin >> n >> m;
  for(int i = 1; i <= n; ++i){
    cin >> a[i];
  }
  sort(a + 1, a + n + 1);
  for(int i = 0; i <= n; ++i){
    for(int j = 0; j <= m; ++j){
      dp[i][j] = INF;
    }
  }
  dp[0][0] = 0;
  for(int i = 1; i <= n; ++i){
    for(int j = 1; j <= 100; ++j){
      for(int k = j * j; k <= m; ++k){
        dp[i][k] = min(dp[i][k], dp[i - 1][k - j * j] + 1ll * abs(a[i] - j) * abs(a[i] - j));
      }
    }
  }
  cout << (dp[n][m] == INF ? -1 : dp[n][m]);
  return 0;
}

B luoguP3029

對位置從小到大排序, 雙指標不斷的把元素刪除, 壓入元素。

時間複雜度 \(O(n \log n)\)

#include<bits/stdc++.h>

using namespace std;

const int N = 50005;

struct Node{
  int x, id;
}a[N];

int n, last, tot, sum, ans = 2e9, cnt[N];
vector<int>v;

int main(){
  freopen("lineup.in", "r", stdin);
  freopen("lineup.out", "w", stdout);
  ios::sync_with_stdio(0), cin.tie(0);
  cin >> n;
  for(int i = 1; i <= n; ++i){
    cin >> a[i].x >> a[i].id;
    v.push_back(a[i].id);
  }
  sort(a + 1, a + n + 1, [](const Node &i, const Node &j){  return i.x < j.x;});
  sort(v.begin(), v.end());
  last = -1;
  for(auto x : v){
    if(last != x){
      last = x;
      tot++;
    }
  }
  for(int i = 1; i <= n; ++i){
    a[i].id = lower_bound(v.begin(), v.end(), a[i].id) - v.begin();
  }
  for(int l = 1, r = 1; r <= n; ++r){
    sum += !cnt[a[r].id];
    cnt[a[r].id]++;
    for(; l <= r && cnt[a[l].id] >= 2; cnt[a[l].id]--, l++){
    }
    if(sum == tot){
      ans = min(ans, a[r].x - a[l].x);
    }
  }
  cout << ans;
  return 0;
}

C luoguP2176

搜出一條最段路, 列舉每一條在最短路上的邊, 取出把草放在上面之後的最短路。

最短路最多隻有 \(n - 1\) 條邊。

時間複雜度 \(O(n^3)\)

#include<bits/stdc++.h>

using namespace std;

const int N = 105, M = 10005;

struct Node{
  int a, b;
}pre[N];

struct cmp{
  bool operator()(const Node &i, const Node &j){
    return i.b > j.b;
  }
};

int n, m, vis[N], dist[N], maxx, id, u, v, w[M], ans, op;
vector<Node>g[N];
vector<int>e;
priority_queue<Node, vector<Node>, cmp>pq;

void dij(int s){
  for(int i = 1; i <= n; ++i){
    vis[i] = 0, dist[i] = 1e9;
  }
  dist[s] = 0;
  for(int i = 1; i < n; ++i){
    maxx = 1e9 + 1, id = -1;
    for(int j = 1; j <= n; ++j){
      if(maxx > dist[j] && !vis[j]){
        maxx = dist[j];
        id = j;
      }
    }
    if(id == -1){
      continue;
    }
    vis[id] = 1;
    //cout << maxx <<' ' << id <<'\n';
    for(auto [u, wd] : g[id]){
      if(dist[u] > dist[id] + w[wd]){
        dist[u] = dist[id] + w[wd];
        pre[u] = {id, wd};
      }
    }
  }
}

void DFS(int x){
  if(!x){
    return;
  }
  DFS(pre[x].a);
  if(pre[x].a){
    e.push_back(pre[x].b);
  }
}

int main(){
  ios::sync_with_stdio(0), cin.tie(0);
  freopen("rblock.in", "r", stdin);
  freopen("rblock.out", "w", stdout);
  cin >> n >> m;
  for(int i = 1; i <= m; ++i){
    cin >> u >> v >> w[i];
    g[u].push_back({v, i});
    g[v].push_back({u, i});
  }
  dij(1);
  op = dist[n];
  DFS(n);
  for(auto x : e){
    w[x] *= 2;
    dij(1);
    ans = max(ans, dist[n] - op);
    w[x] /= 2;
  }
  cout << ans;
  return 0;
}