1. 程式人生 > 實用技巧 >b_lg_連續攻擊遊戲(反向思維+記憶化搜尋)

b_lg_連續攻擊遊戲(反向思維+記憶化搜尋)

一開始的時候,lxhgww只能使用某個屬性值為1的裝備攻擊boss,然後只能使用某個屬性值為2的裝備攻擊boss,
然後只能使用某個屬性值為3的裝備攻擊boss……以此類推。現在lxhgww想知道他最多能連續攻擊boss多少次?

思路
這本是一道二分圖的題,但我很生氣我沒學過,所以一氣之下寫了個50/100的正向暴搜

#include<bits/stdc++.h>
using namespace std;
const int N=1e7+5;
int n, a[N][2], st[N], ans;
void dfs(int attr) {
    if (attr>ans) ans=attr;
    for (int j=1; j<=n; j++) if (!st[j] && (attr+1==a[j][0] || attr+1==a[j][1])) {
        st[j]=1;
        dfs(attr+1);
        st[j]=0;        
    }
}
int main() {
    std::ios::sync_with_stdio(false); cin.tie(0); cout.tie(0);
    cin>>n; for (int i=1; i<=n; i++) cin>>a[i][0]>>a[i][1];
    for (int i=1; i<=n; i++) if (a[i][0]==1 || a[i][1]==1) {
        st[i]=1;
        dfs(1);
        st[i]=0;
    }
    cout<<ans;
    return 0;
}

想著加入記憶化加速,但上面的程式碼即使加入記憶化也無法擺脫main函式中的for迴圈
反向思維優化:將每個武器的屬性和屬性id換過來儲存,即 a[x].push_back(id), a[y].push_back(id)

#include<bits/stdc++.h>
using namespace std;
const int N=1e6+5;
int st[N], f[N], ans;
vector<int> a[N];
int dfs(int attr) {
    if (f[attr]) return f[attr];
    int t=0;
    for (int& id : a[attr]) if (!st[id]) { //該attr對應的武器編號
        st[id]=1;
        t=max(t,dfs(attr+1)+1);
        st[id]=0;
    }
    return f[attr]=t;
}
int main() {
    std::ios::sync_with_stdio(false); cin.tie(0); cout.tie(0);
    int n; cin>>n;
    for (int i=1; i<=n; i++) {
        int x,y; cin>>x>>y;
        a[x].push_back(i), a[y].push_back(i);
    }
    cout<<dfs(1);
    return 0;
}