dp
我在一开始的时候也想要用dp去做,但是发现,对于占据一个节点
我们可以在当前位置占据他,也可以在之后占据他。
这一就意味着我峨嵋你的dp具有后效性,那么就不能dp了
苦恼啊苦恼。
后来发现,这里其实是一个简单的贪心。
对于占据一个节点,很明显我们在能占据他的节点中的最后面占据他就好了!
这个贪心至关重要,他帮助了我们解决了dp的后效性问题。
那么我们就可以利用dp了。
dp[i][j]到第i个位置上,拥有j个士兵(还没在当前节点招募士兵)从这之后的最大收益。
很明显,我们可以不去防守节点,直接去占据下一个节点。
当饭我们也可以去占据节点。如何占据呢?
我们从大到小的占据,优先占据性价比最高的嘛。
如此,我们便完成了!!!!
真的是,如果没有意识到那个贪心真的是很难做出来的!!!!!
#include<iostream> #include<algorithm> #include<vector> #include<functional> using namespace std; const int max_n = 5500; typedef long long ll; const ll inf = 1e9; int n,m,k; ll a[5500],b[5500],c[5500]; int last[max_n]; int dp[5500][5500]; bool vis[5500][5500]; vector<int> G[5500]; ll Solve(int ii,int jj){ if (vis[ii][jj])return dp[ii][jj]; vis[ii][jj]=true; if (jj<a[ii])return dp[ii][jj]=-inf; if (ii==n+1)return dp[ii][jj]=0; ll ans = Solve(ii+1,jj+b[ii]); ll sum = 0; for (int i=0;i<G[ii].size();++i){ sum += G[ii][i]; if (jj-i-1+b[ii]<0)break; ans = max(ans,Solve(ii+1,jj-i-1+b[ii])+sum); }return dp[ii][jj]=ans; } int main(){ ios::sync_with_stdio(0); cin>>n>>m>>k; for (int i=1;i<=n;++i)cin>>a[i]>>b[i]>>c[i]; for (int i=1;i<=n;++i)last[i]=i; for (int i=1;i<=m;++i){ int u,v;cin>>u>>v; if (u>v)swap(u,v); last[u]=max(last[u],v); } for (int i=1;i<=n;++i)G[last[i]].push_back(c[i]); for (int i=1;i<=n;++i)sort(G[i].begin(),G[i].end(),greater<ll>()); ll ans = Solve(1,k); if (ans<0)cout<<-1<<endl; else cout<<ans<<endl; }