1456 Supermarket (貪心, 並查集)
阿新 • • 發佈:2018-12-15
#include<cstdio> #include<cstring> #include<algorithm> #include<queue> using namespace std; const int N = 10005; struct Node{ int px, dx; friend bool operator<(const Node&a,const Node&b){ return a.px>b.px; } }arr[N]; int n; //簡單的貪心就可以解決,當然是選擇利潤優先,然後把截止日期給佔掉 //如果已經給佔用了,那就往前推一天 int main(){ while(~scanf("%d",&n)){ int maxTime=0; for(int i=0; i<n; ++i){ scanf("%d%d",&arr[i].px, &arr[i].dx); if(arr[i].dx>maxTime) maxTime = arr[i].dx; } sort(arr,arr+n); bool vis[N]; memset(vis, 0, sizeof(vis)); int ans = 0, pos=0; for(int i=0; i<n; ++i){ if(!vis[arr[i].dx]){ ans += arr[i].px; vis[arr[i].dx] = true; } else{ for(int j=arr[i].dx-1; j>=1; --j)if(!vis[j]){ ans += arr[i].px; vis[j] = true; break; } } } printf("%d\n", ans); } return 0; }
#include<cstdio> #include<cstring> #include<algorithm> #include<queue> using namespace std; const int N = 10005; struct Node{ int px, dx; friend bool operator<(const Node&a,const Node&b){ return a.px>b.px; } }arr[N]; int f[N],n; inline void init(int n){ for(int i=0; i<=n; ++i) f[i]=i; } int find(int x){//找到沒有被佔用的最後那一天 /*假設一個產品a佔用了一個日期後,那麼如果下次又有一個產品b和產品a的截止日期是相同的,但是那個日期以被佔用了,所以就要往前移動1天,那麼就可以用並查集進行標記,在a佔用了那個日期後,把a的截止日期指向前一個日期,這樣的話,可以直接查詢到他要佔用到哪一個時間*/ int i, j=x; while(j!=f[j]) j=f[j]; while(x!=j){ i=f[x]; f[x]=j; x=i;//把相關的都修改一下 } return j; } int main(){ while(~scanf("%d",&n)){ int maxTime=0; for(int i=0; i<n; ++i){ scanf("%d%d",&arr[i].px, &arr[i].dx); if(arr[i].dx>maxTime) maxTime = arr[i].dx; } init(maxTime); sort(arr,arr+n); int ans = 0; for(int i=0; i<n; ++i){ int d = find(arr[i].dx); if(d>0){ ans += arr[i].px; f[d] = d-1; } } printf("%d\n", ans); } return 0; }