题意:
n个点,用水平线或者竖直线划分成k条,要求平均差最小,平均差为每条中点的个数减去n/k的绝对值。
解法:
首先一看就是个DP,与处理不说了,用水平扫描线、竖直扫描线将同一直线上的点压缩成一个带权值的点,然后DP
这题重要的是DP降维
观察DP方程
dp[i]=min{dp[j]+|sum[i]-sum[j]-average|}
这里就要分成两部分讨论
1、当sum[i]-sum[j]>average时
dp[i]=min{dp[j]+sum[i]-sum[j]-average}
这就是一个变量“打擂台”的问题,从前向后扫,维护一个dp[j]-sum[j]的最小值即可。
2、当sum[i]-sum[j]<average时
dp[i]=min{dp[j]+average-sum[i]+sum[j]}
这里打擂台就不行了,因为区间是移动着的。开始偷懒,直接用STL的set动态维护一个dp[j]+sum[j]的最小值。。果断TLE。。汗。。
木办法。。化简方程吧
把sum[j]看作横坐标,dp[j]看作纵坐标,转化为斜率优化问题
dp[j]=-sum[j]+sum[i]-average+dp[i]
令sum[i]-average+dp[i]=A
方程化为
dp[j]=-sum[j]+A
为了让A最小,就是找到个j,使得dp[j]+sum[j]最小,然后就是斜率优化的经典方法了,用栈队列
当dp[k]+sum[k]>dp[j]+sum[j],j>k的时候,k退栈,然后将j压栈
在栈的底端,将不符合要求的状态,即sum[i]-sum[j]>average,i>j的队头状态j给出队。这样,队头的元素就为最优值
所有元素顶多进队一次,出队一次,复杂度O(n)
总复杂度为O(k*m)
不知道怎么回事。。在POJ上死都TLE。。本机秒解,HDU500MS,可能分数类写的有点搓了。。把代码贴出来,大家看看哪里能修正修正。。。好想好想把poj给过了啊。
1
# include <cstdio>
2
using namespace std;
3
# include <vector>
4
# include <algorithm>
5
# include <utility>
6
# include <functional>
7
# include <map>
8
# include <cstring>
9
# define abs(num) ((num)>0?(num):-(num))
10
# define eps 1e-6
11
struct func
12

{
13
int up,down;
14
func()
{}
15
func(int num):up(num),down(1)
{}
16
int gcd(int a,int b)
17
{
18
if(!b) return a;
19
else return gcd(b,a%b);
20
}
21
void simple()
22
{
23
int t=gcd(abs(up),abs(down));
24
up/=t;
25
down/=t;
26
if(down<0) up*=-1,down*=-1;
27
}
28
func operator+(const func &pos)
29
{
30
func res;
31
res.down=down*pos.down;
32
res.up=up*pos.down+pos.up*down;
33
res.simple();
34
return res;
35
}
36
func operator-(const func &pos)
37
{
38
func res;
39
res.down=down*pos.down;
40
res.up=up*pos.down-pos.up*down;
41
res.simple();
42
return res;
43
}
44
bool operator<(const func &pos) const
45
{
46
return up*pos.down<pos.up*down;
47
}
48
bool operator==(const func &pos) const
49
{
50
return up==pos.up&&down==pos.down;
51
}
52
bool operator!=(const func &pos) const
53
{
54
return up!=pos.up||down!=pos.down;
55
}
56
bool operator<=(const func &pos) const
57
{
58
return *this<pos||*this==pos;
59
}
60
61
};
62
int data[100000],de;
63
func dp[10][100000];
64
func aver;
65
int k;
66
int q[100000];
67
func num[100000];
68
struct cmp
69

{
70
bool operator()(const pair<int,int> &a,const pair<int,int> &b) const
71
{
72
if(dp[a.first][a.second]+func(data[a.second])!=dp[b.first][b.second]+func(data[b.second]))
73
return dp[a.first][a.second]+func(data[a.second])<dp[b.first][b.second]+func(data[b.second]);
74
else return a.second<b.second;
75
}
76
};
77
func min(func a,func b)
78

{
79
if(a.up*b.down<b.up*a.down) return a;
80
else return b;
81
}
82
func solve()
83

{
84
for(int i=0;i<de;i++)
85
num[i]=func(data[i]);
86
int down=aver.up/aver.down,up=aver.up%aver.down?aver.up/aver.down+1:aver.up/aver.down;
87
for(int i=0;i<de;i++)
88
if(data[i]<=down) dp[0][i]=aver-num[i];
89
else dp[0][i]=num[i]-aver;
90
for(int i=1;i<k;i++)
91
{
92
for(int j=0;j<de;j++)
93
dp[i][j]=dp[i-1][j]+aver;
94
int last=-1;
95
func ans=func(0xfffffff);
96
for(int j=0;j<de;j++)
97
{
98
while(data[j]-data[last+1]>=up)
99
{
100
last++;
101
if(!last) ans= dp[i-1][last]-num[last]-aver;
102
else ans=min(ans,dp[i-1][last]-num[last]-aver);
103
}
104
if(last!=-1)
105
dp[i][j]=min(dp[i][j],ans+num[j]);
106
107
}
108
int s=-1,e=0;
109
q[0]=0;
110
for(int j=1;j<de;j++)
111
{
112
//add
113
while(s!=e&&dp[i-1][j]+num[j]<=dp[i-1][q[e]]+num[q[e]])
114
e--;
115
q[++e]=j;
116
//erase
117
while(s!=e&&data[j]-data[q[s+1]]>down) s++;
118
if(s!=e)
119
dp[i][j]=min(dp[i][j],dp[i-1][q[s+1]]+aver-num[j]+num[q[s+1]]);
120
121
}
122
}
123
return dp[k-1][de-1];
124
125
}
126
int main()
127

{
128
//freopen("land.in","r",stdin);
129
//freopen("ans.txt","w",stdout);
130
pair<int,int> d[100000];
131
map<int,int> refer;
132
int n,test=1;
133
while(scanf("%d%d",&n,&k)!=EOF&&(n||k))
134
{
135
refer.clear();
136
aver.up=n;
137
aver.down=k;
138
aver.simple();
139
for(int i=0;i<n;i++)
140
scanf("%d%d",&d[i].first,&d[i].second);
141
for(int i=0;i<n;i++)
142
refer[d[i].first]++;
143
data[0]=0;
144
de=1;
145
for(map<int,int>::iterator i=refer.begin();i!=refer.end();i++)
146
data[de++]=(i->second);
147
for(int i=1;i<de;i++)
148
data[i]+=data[i-1];
149
150
func ans=solve();
151
refer.clear();
152
for(int i=0;i<n;i++)
153
refer[d[i].second]++;
154
data[0]=0;
155
de=1;
156
for(map<int,int>::iterator i=refer.begin();i!=refer.end();i++)
157
data[de++]=(i->second);
158
for(int i=1;i<de;i++)
159
data[i]+=data[i-1];
160
ans=min(ans,solve());
161
ans.down*=k;
162
ans.simple();
163
printf("%d. %d/%d\n",test++,ans.up,ans.down);
164
}
165
return 0;
166
}
。