hdoj 5681 zxa and wifi

来源:互联网 发布:17%退税率出口退税算法 编辑:程序博客网 时间:2024/06/06 05:09

  比赛的时候撸了个dp,用线段树优化状态转移,无限T。。然后题解的O(nk)看不懂,后来终于自己想出另外一种O(nk+nlog(n))的写法,感觉可能和题解是一个意思。
  dp(i,j)表示前i户人家装了j个WIFI的最优解,转移的时候外层循环用j,即可以理解为一个一个加WIFI。如果第i户人家的WIFI最右边可以照顾到第ri户人家,最左边到li,那么只需要从li1转移到ri,中间那些不用管,然后倒着刷一遍取min就好了。

#include <iostream>    #include <stdio.h>    #include <cmath>    #include <algorithm>    #include <string>  #include <string.h>       #include <vector>    #include <queue>    #include <stack>#include <map>using namespace std;#define ll long longint dp[20010][110];int d[20010];int a[20010];int b[20010];int r[20010];int pos[20010];int leftMost[20010];int rightMost[20010];const int INF = 2e9;struct seg{    int id;    int l,r;    bool operator<(const seg &other){        return r<other.r;    }}s[20010];int main(){    int t;    cin>>t;    while(t--){        int n,k;        cin>>n>>k;        for(int i=1;i<n;i++){            scanf("%d",&d[i]);            pos[i+1] = pos[i] + d[i];        }        for(int i=1;i<=n;i++){            scanf("%d%d%d",&a[i],&r[i],&b[i]);        }        for(int i=1;i<=n;i++){            leftMost[i] = lower_bound(pos+1,pos+n+1,pos[i]-r[i]) - (pos);        }        for(int i=1;i<=n;i++){            rightMost[i] = lower_bound(pos+1,pos+n+1,pos[i]+r[i]+1) - (pos+1);        }        for(int i=1;i<=n;i++){            s[i].id = i;            s[i].l = leftMost[i];            s[i].r = rightMost[i];        }        sort(s+1,s+n+1);        for(int i=1;i<=n;i++){            dp[i][0] = dp[i-1][0] + b[i];        }        for(int j=1;j<=k;j++){            for(int i=1;i<=n;i++){                dp[i][j] = dp[i][j-1];            }            for(int i = 1;i<=n;i++){                dp[s[i].r][j] = min(dp[s[i].r][j],dp[s[i].l-1][j-1]+a[s[i].id]);            }            for(int i = 1;i<=n;i++){                dp[i][j] = min(dp[i][j],dp[i-1][j]+b[i]);            }            for(int i = n-1;i>=1;i--){                dp[i][j] = min(dp[i][j],dp[i+1][j]);            }        }        int ans = INF;        for(int i=0;i<=k;i++){            int tmp = dp[n][i];            ans = min(ans,tmp);        }        cout<<ans<<endl;    }    return 0;}
0 0
原创粉丝点击