您的位置:首页 > 其它

HDU 4293 Groups

2012-09-16 18:55 381 查看
  每个有效的(A,B),都能对应到一个group的区间[A+1,N-B]。把每个group看作一个节点,权值为这个group的player出现的次数(且不能超过区间长度)。若两个区间不冲突,从左边的区间向右边的连一条有向边。加上源点和终点(连上所有节点),求最长路。

//2012-09-16 18:56:27	Accepted	4293	156MS	2260K	1900 B	G++	Aros
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<queue>
using namespace std;
const int MAXN = 500+5, MAXM = 300000+5;
const int INF = 0x3f3f3f3f;
int N, a, b, A[MAXN], B[MAXN];
int n, s, t, mp[MAXN][MAXN];
int val[MAXN], d[MAXN];
int e, head[MAXN], next[MAXM], v[MAXM];
bool inq[MAXN];
queue<int> Q;
void addedge(int x, int y)
{
v[e] = y;
next[e] = head[x]; head[x] = e++;
}
void spfa()
{
for (int i = 1; i <= n; i++)
d[i] = 0;
memset(inq, 0, sizeof(inq));
Q.push(s);
while (!Q.empty())
{
int u = Q.front(); Q.pop();
inq[u] = 0;
for (int i = head[u]; i != -1; i = next[i])
if (d[v[i]] < d[u]+val[v[i]])
{
d[v[i]] = d[u]+val[v[i]];
if (!inq[v[i]])
{
Q.push(v[i]);
inq[v[i]] = 1;
}
}
}
}
int main()
{
while (scanf("%d", &N) != EOF)
{
e = 0; n = 0;
memset(head, -1, sizeof(head));
memset(mp, 0, sizeof(mp));
memset(val, 0, sizeof(val));
for (int i = 1; i <= N; i++)
{
scanf("%d%d", &a, &b);
if (a+b >= N)
continue;
int x = a+1, y = N-b, &m = mp[x][y];
if (!m)
{
m = ++n;
A[m] = x;
B[m] = y;
}
val[m] = min(B[m]-A[m]+1, val[m]+1);
}
for (int i = 1; i <= n; i++)
for (int j = 1; j <= n; j++)
if (B[i] < A[j])
addedge(i, j);
s = n+1, t = n+2; val[s] = val[t] = 0;
for (int i = 1; i <= n; i++)
addedge(s, i), addedge(i, t);
n += 2;
spfa();
printf("%d\n", d[t]);
}
return 0;
}


  更新dp解法,d[i]表示长度为i且包含以I结尾的区间时最大的人数。

//2012-09-20 16:05:55	Accepted	4293	46MS	1224K	1178 B	G++	Aros
#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
const int MAXN = 500+5;
const int INF = 0x3f3f3f3f;
int N, a, b, A[MAXN], B[MAXN], r[MAXN];
int mp[MAXN][MAXN], num[MAXN], d[MAXN];
bool cmp(const int a, const int b)
{
return B[a] < B[b];
}
int main()
{
while (scanf("%d", &N) != EOF)
{
memset(mp, 0, sizeof(mp));
memset(num, 0, sizeof(num));
memset(d, 0, sizeof(d));
int n = 0, ans = 0;
for (int i = 1; i <= N; i++)
{
scanf("%d%d", &a, &b);
if (a+b >= N)
continue;
int &m = mp[a+1][N-b];
if (!m)
{
m = ++n;
A
= a+1;
B
= N-b;
r
= n;
}
num[m] = min(num[m]+1, N-a-b);
}
sort(r+1, r+1+n, cmp);
for (int i = 1; i <= n; i++)
for (int j = 0; j < A[r[i]]; j++)
d[B[r[i]]] = max(d[B[r[i]]], d[j]+num[r[i]]);
for (int i = 1; i <= N; i++)
ans = max(ans, d[i]);
printf("%d\n", ans);
}
return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: