[dp]HDOJ4960 Another OCD Patient

题意: 给一个n, 第二行给n堆的价值v[i], 第三行给a[i].  a[i]表示把i堆合在一起需要的花费.

  求把n堆变成类似回文的 需要的最小花费.

 

思路:

①记忆化搜索 比较好理解...

 dp[l][r] 记录l到r的最小花费

枚举对称轴 维护每次l到r之间对称 

dp[l][r]=min(dp[l][r], a[cur-l]+a[r-i]+dfs(cur+1, i-1));

 l左边和r右边的合并

[dp]HDOJ4960 Another OCD Patient
 1 #include <cstdio>

 2 #include <cstdlib>

 3 #include <cstring>

 4 #include <climits>

 5 #include <cctype>

 6 #include <cmath>

 7 #include <string>

 8 #include <sstream>

 9 #include <iostream>

10 #include <algorithm>

11 #include <iomanip>

12 using namespace std;

13 #include <queue>

14 #include <stack>

15 #include <vector>

16 #include <deque>

17 #include <set>

18 #include <map>

19 typedef long long LL;

20 typedef long double LD;

21 #define pi acos(-1.0)

22 #define lson l, m, rt<<1

23 #define rson m+1, r, rt<<1|1

24 typedef pair<int, int> PI;

25 typedef pair<int, PI> PP;

26 #ifdef _WIN32

27 #define LLD "%I64d"

28 #else

29 #define LLD "%lld"

30 #endif

31 //#pragma comment(linker, "/STACK:1024000000,1024000000")

32 //LL quick(LL a, LL b){LL ans=1;while(b){if(b & 1)ans*=a;a=a*a;b>>=1;}return ans;}

33 //inline int read(){char ch=' ';int ans=0;while(ch<'0' || ch>'9')ch=getchar();while(ch<='9' && ch>='0'){ans=ans*10+ch-'0';ch=getchar();}return ans;}

34 inline void print(LL x){printf(LLD, x);puts("");}

35 //inline void read(double &x){char c = getchar();while(c < '0') c = getchar();x = c - '0'; c = getchar();while(c >= '0'){x = x * 10 + (c - '0'); c = getchar();}}

36 

37 int a[5005];

38 LL num[5005];

39 int cost[5005];

40 int dp[5005][5005];

41 int dfs(int l, int r)

42 {

43     if(dp[l][r]!=-1)

44         return dp[l][r];

45     if(l>=r)

46         return dp[l][r]=0;

47     dp[l][r]=cost[r-l];

48     int cur=l;

49     for(int i=r;i>=l;i--)

50     {

51         for(;cur<i && (num[cur]-num[l-1]<num[r]-num[i-1]);cur++);

52         if(cur==i)

53             break;

54         if(num[cur]-num[l-1]==num[r]-num[i-1])

55             dp[l][r]=min(dp[l][r], cost[cur-l]+cost[r-i]+dfs(cur+1, i-1));

56     }

57     return dp[l][r];

58 }

59 int main()

60 {

61 #ifndef ONLINE_JUDGE

62     freopen("in.txt", "r", stdin);

63     freopen("out.txt", "w", stdout);

64 #endif

65     int n;

66     while(~scanf("%d", &n) && n)

67     {

68         num[0]=0;

69         for(int i=1;i<=n;i++)

70         {

71             scanf("%d", &a[i]);

72             num[i]=num[i-1]+(LL)a[i];

73         }

74         for(int i=0;i<n;i++)

75             scanf("%d", &cost[i]);

76         for(int i=0;i<=n;i++)

77             fill(dp[i]+i+1, dp[i]+n+1, -1);

78         //memset(dp, -1, sizeof(dp));

79         printf("%d\n", dfs(1, n));

80     }

81     return 0;

82 }
HDOJ 4960 记忆化搜索

 

② 区间dp

结构体里有 SUM和NUM记录 左或右 NUM堆合起来 合成总值为SUM的

左边从1开始往右 右边从n开始往左

Lsum==Rsum了就分别把Lsum合起来 Rsum合起来 分别存进L和R   然后继续往中间  

Ltmp和Rtmp分别记录左边和右边分别合到哪里了

 

L R 搞完以后 按顺序把 L 中间 R 放进final (注意中间)

因为对称 所以只要 dp  final 的一半就够了

dp[i]=min(dp[i], dp[j]+cost[左个数]+cost[右个数]);

 

最后要注意合了 i堆之后 把剩下的全合起来的情况

ans=min(ans, dp[i]+cost[剩下堆数]);

[dp]HDOJ4960 Another OCD Patient
  1 #include <cstdio>

  2 #include <cstdlib>

  3 #include <cstring>

  4 #include <climits>

  5 #include <cctype>

  6 #include <cmath>

  7 #include <string>

  8 #include <sstream>

  9 #include <iostream>

 10 #include <algorithm>

 11 #include <iomanip>

 12 using namespace std;

 13 #include <queue>

 14 #include <stack>

 15 #include <vector>

 16 #include <deque>

 17 #include <set>

 18 #include <map>

 19 typedef long long LL;

 20 typedef long double LD;

 21 #define pi acos(-1.0)

 22 #define lson l, m, rt<<1

 23 #define rson m+1, r, rt<<1|1

 24 typedef pair<int, int> PI;

 25 typedef pair<int, PI> PP;

 26 #ifdef _WIN32

 27 #define LLD "%I64d"

 28 #else

 29 #define LLD "%lld"

 30 #endif

 31 //#pragma comment(linker, "/STACK:1024000000,1024000000")

 32 //LL quick(LL a, LL b){LL ans=1;while(b){if(b & 1)ans*=a;a=a*a;b>>=1;}return ans;}

 33 //inline int read(){char ch=' ';int ans=0;while(ch<'0' || ch>'9')ch=getchar();while(ch<='9' && ch>='0'){ans=ans*10+ch-'0';ch=getchar();}return ans;}

 34 inline void print(LL x){printf(LLD, x);puts("");}

 35 //inline void read(double &x){char c = getchar();while(c < '0') c = getchar();x = c - '0'; c = getchar();while(c >= '0'){x = x * 10 + (c - '0'); c = getchar();}}

 36 

 37 struct node

 38 {

 39     LL SUM;

 40     int NUM;

 41 }L[5005], R[5005], final[5005];

 42 LL dp[5005];

 43 int a[5005];

 44 int cost[5005];

 45 int Ltop, Rtop, top;

 46 int main()

 47 {

 48 #ifndef ONLINE_JUDGE

 49     freopen("in.txt", "r", stdin);

 50     freopen("out.txt", "w", stdout);

 51 #endif

 52     int n;

 53     while(~scanf("%d", &n) && n)

 54     {

 55         memset(L, 0, sizeof(L));

 56         memset(R, 0, sizeof(R));

 57         memset(final, 0, sizeof(final));

 58         memset(a, 0, sizeof(a));

 59         memset(cost, 0, sizeof(cost));

 60         for(int i=1;i<=n;i++)

 61             scanf("%d", &a[i]);

 62         for(int i=1;i<=n;i++)

 63             scanf("%d", &cost[i]);

 64 

 65         LL Lsum=a[1], Rsum=a[n];

 66         int Lnum=1, Rnum=1;

 67         Ltop=Rtop=0;

 68         int Ltmp=1, Rtmp=n;

 69         for(int i=1, j=n; i<j;)

 70         {

 71             while(Lsum!=Rsum)

 72             {

 73                 if(i==j)

 74                     break;

 75                 if(Lsum<Rsum)

 76                 {

 77                     Lnum++;

 78                     Lsum+=a[++i];

 79                 }

 80                 else if(Rsum<Lsum)

 81                 {

 82                     Rnum++;

 83                     Rsum+=a[--j];

 84                 }

 85             }

 86             if(Lsum==Rsum)

 87             {

 88                 L[Ltop].SUM=Lsum, L[Ltop++].NUM=Lnum;

 89                 R[Rtop].SUM=Rsum, R[Rtop++].NUM=Rnum;

 90                 Lsum=a[++i];

 91                 Rsum=a[--j];

 92                 Lnum=Rnum=1;

 93                 Ltmp=i;

 94                 Rtmp=j;

 95             }

 96         }

 97         top=0;

 98         for(int i=0;i<Ltop;i++)

 99             final[++top]=L[i];

100         if(Ltmp<=Rtmp)

101         {

102             int sum=0;

103             for(int i=Ltmp;i<=Rtmp;i++)

104                 sum+=a[i];

105             final[++top].SUM=sum, final[top].NUM=Rtmp-Ltmp+1;

106         }

107         for(int i=Rtop-1;i>=0;i--)

108             final[++top]=R[i];

109         for(int i=1;i<=top/2;i++)

110         {

111             int tmp1=final[i].NUM, tmp2=final[top-i+1].NUM;

112             dp[i]=LLONG_MAX;

113             for(int j=i-1;j>=0;j--)

114             {

115                 dp[i]=min(dp[i], dp[j]+cost[tmp1]+cost[tmp2]);

116                 tmp1+=final[j].NUM;

117                 tmp2+=final[top-j+1].NUM;

118             }

119         }

120         LL minn=LLONG_MAX;

121         LL ans=n;

122         for(int i=0;i<=top/2;i++)

123         {

124             minn=min(minn, dp[i]+cost[ans]);

125             ans-=final[i+1].NUM+final[top-i].NUM;

126         }

127         print(minn);

128     }

129     return 0;

130 }
HDOJ 4960 区间dp

 

你可能感兴趣的:(pat)