luogu P1250 種樹
阿新 • • 發佈:2018-12-20
我來總結一下最常用的兩種辦法
1.貪心
2.差分約束
那麼我們先來講,貪心版《種樹》
大家可能知道有一個題和這個類似,那個是釘釘子而這個是種樹
我們可以借用釘釘子的思路來想,首先這個是讓你求最小值,而且每個人都有自己劃定的區間,並且他們還要求在這段區間內最少種T棵樹。
那麼我們既要滿足最少種樹數,而且要滿足每個人的要求。好在的是,題目中說過區間和區間之間可能會有一段重疊,那麼我們要抓住這個機會盡可能多的在每一段重複區間內多種樹,所以就會產生一個連鎖反應,就是上一個重複區間內種的樹可能會滿足下一個人的要求,那麼這個人就可以略過去,以達到最少數的目的。
(以下是貪心程式碼,體會一下)
#include<bits/stdc++.h> using namespace std; const int N = 31000; int n,m,ans=0; bool u[N]={0}; struct Edge{ int x,y,z; }a[N]; bool cmp(Edge a,Edge b) { return a.y<b.y; } int main() { cin>>n>>m; for(int i=1;i<=m;i++) cin>>a[i].x>>a[i].y>>a[i].z; sort(a+1,a+m+1,cmp); for(int i=1;i<=m;i++) { int sum=0; for(int j=a[i].x;j<=a[i].y;j++) if(u[j]) sum++;//統計已有的數量 if(sum>=a[i].z) continue;//滿足就繼續 for(int k=a[i].y;k>=a[i].x;k--)//不滿足情況 { if(!u[k]) { u[k]=1; sum++; ans++;//答案++ if(sum==a[i].z) break;//直到滿足,退出 } } } cout<<ans;//輸出最後答案(即最少的樹的數量) return 0; }
接下來我們講,差分約束版《種樹》
我們都知道差分約束是用於最短路不等式問題的
這裡我們利用差分約束解決最短路不等式的性質來看
我們想在區間內種最少的樹,所以根據性質
我們可以列出兩個差分約束公式
1.sum[x]-sum[y-1]>=c;(這裡是指在區間[y,x]中至少種c棵樹)
2.0<=sum[x]-sum[x-1]<=1;(這裡是指一個單位長度內最多種1棵樹)
根據公式,我們可以建邊,但是建邊是y+1->y=-1而不是y->y+1=1
建好邊我們就可以跑一邊SPFA啦,最少種樹數也就出來了!
(差分約束程式碼,體會一下)
#include<bits/stdc++.h> using namespace std; const int N = 31000; const int M = 110000; int n,m; int dis[N]; bool vis[N]; int head[N],num; struct Edge{ int to,next,w; }s[M]; void add(int u,int v,int w)//根據公式建邊 { s[++num].w=w; s[num].next=head[u]; head[u]=num; s[num].to=v; } void spfa(int x)//SPFA經典操(ban)作(zi) { queue<int> q; q.push(x); for(int i=0;i<=n+1;i++) dis[i]=1; dis[x]=0;vis[x]=1; while(!q.empty()) { int g=q.front(); q.pop(); vis[g]=0; for(int i=head[g];i!=-1;i=s[i].next) { int t=s[i].to; if(dis[t]>dis[g]+s[i].w) { dis[t]=dis[g]+s[i].w; if(!vis[t]) { q.push(t); vis[t]=1; } } } } } int main() { int a,b,c,minn=123456789; memset(head,-1,sizeof(head)); cin>>n>>m; int y=n+1; for(int i=0;i<=n;i++) add(y,i,0); for(int i=1;i<=m;i++) { cin>>a>>b>>c; add(b,a-1,-c); } for(int i=1;i<=n;i++)//建邊操作 { add(i-1,i,1); add(i,i-1,0); } spfa(y); for(int i=0;i<=n;i++)//取最小值 minn=min(minn,dis[i]); cout<<dis[n]-minn<<endl; return 0; }
煙雨江南,無你何歡!