1. 程式人生 > >有線電視網(信心題)

有線電視網(信心題)

信心題 沒想到,在NOIP前一天還能找到信心。 今天上午,本來有個班主任(生物老師)的生物小測,老師問我要不要去練會程式碼,我想了想,還是來了。 於是40分鐘,A了這道藍題。 其實就是dp,用f[u][k]表示節點u取k個使用者時的最小花費(可能為負) 轉移方程也很好寫,f[u][k]=min{f[u][k-i]+f[v][i]}(v為u的子節點,i為列舉的量) 所以程式碼也就出來了:

#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
const int MAXN=
3005; int n,m; int f[MAXN][MAXN]; int mapp[MAXN][MAXN]; int vis[MAXN]; //int fee[MAXN]; void solve(int cur){ if(vis[cur]){ return; } vis[cur]=1; for(int i=1;i<=n;i++){ if(mapp[cur][i]!=-1){ solve(i); for(int j=m;j>=0;j--){ if(f[cur][j]<0x3f3f3f3f){ for(int k=0;k<=m;k++){ if
(f[i][k]<0x3f3f3f3f){ f[cur][j+k]=min(f[cur][j+k],f[i][k]+f[cur][j]+mapp[cur][i]); } } } } } } } int main(){ scanf("%d%d",&n,&m); memset(mapp,-1,sizeof(mapp)); memset(f,0x3f,sizeof(f)); memset(vis,0,sizeof(vis)); for(int i=1;i<=(n-m);i++){ int k; scanf
("%d",&k); for(int j=0;j<k;j++){ int a,c; scanf("%d%d",&a,&c); mapp[i][a]=c; f[i][0]=0; } } for(int i=n-m+1;i<=n;i++){ int c; scanf("%d",&c); f[i][1]=-c; f[i][0]=0; vis[i]=1; } solve(1); int ans=-1; for(int i=0;i<=m;i++){ if(f[1][i]<=0){ ans=i; } } printf("%d",ans); return 0; }