分析:
非常裸的DLX。。。比赛的时候不知道。。。所以就呵呵了,还写了个生成树Orz
反思:
看了翁教德板子感觉十分清晰啊
然后我手残了。。。
1.样例输错了一直觉得很奇怪。。。
2.DLX注意点见代码。
3.处理的时候逗逼了,没有把距离为0给加到L数组里面。
看代码吧
AC代码:
翁教好板子:
#include <cstdio>
#include <cstring>
#include <iostream>
#include <vector>
#include <algorithm>
#include <climits>
namespace Links {
const int N = 100;
const int M = N * N;
int R[M], L[M], U[M], D[M], C[M], S[N], O[N], row[M], Col[M];
int size = 0;//列标号不记录到实际的点
void remove(int& c) {
for (int i = D[c]; i != c; i = D[i]) {
L[R[i]] = L[i];
R[L[i]] = R[i];
}
}
void resume(int& c) {
for (int i = U[c]; i != c; i = U[i]) {
L[R[i]] = i;
R[L[i]] = i;
}
}
int h() {//启发式函数,减少时间
bool hash[101];//开大一点
memset(hash, false, sizeof(hash));
int ret = 0;
for (int c = R[0]; c != 0; c = R[c]) {
if (!hash[c]) {
ret ++;
hash[c] = true;
for (int i = D[c]; i != c; i = D[i]) {
for (int j = R[i]; j != i; j = R[j]) {
hash[Col[j]] = true;
}
}
}
}
return ret;
}
int ans = INT_MAX;
void dfs(int deep) {
if (deep + h() >= ans) {//判断是不是已经超过额度K了
return;
}
if (R[0] == 0) {
ans = std::min(ans, deep);
return;
}
int idx, i, j, minnum = 99999;
for (i = R[0]; i != 0; i = R[i]) {//优化,从最大的行开始搜
if (S[i] < minnum) {
minnum = S[i];
idx = i;
}
}
for (i = D[idx]; i != idx; i = D[i]) {
remove(i);
for (j = R[i]; j != i; j = R[j]) {
remove(j);
}
dfs(deep + 1);
for (j = L[i]; j != i; j = L[j]) {
resume(j);
}
resume(i);
}
}
void Init(int n) {
memset(S, 0, sizeof(S));//一定要清空
for (int i = 1; i <= n; ++ i) {
R[i - 1] = L[i + 1] = U[i] = D[i] = i;
}
R[n] = 0;
L[0] = n;
size = n + 1;//点的标号从n+1开始
ans = INT_MAX;//初始化
}
void Add(int i, int x, int& rowh) {
D[U[x]] = size;
U[size] = U[x];
D[size] = x;
U[x] = size;
S[x] ++;
row[size] = i;
Col[size] = x;
if (rowh == -1) {
L[size] = R[size] = size;
rowh = size;
} else {
R[size] = rowh;
L[size] = L[rowh];
R[L[rowh]] = size;
L[rowh] = size;
}
size ++;
}
};
inline int abs(int x) {
return x < 0 ? -x : x;
}
const int N = 100;
struct Point {
int x, y;
Point(int x = 0, int y = 0) : x(x), y(y) {}
long long Dist(const Point& p) const {
return (long long)abs(x - p.x) + abs(y - p.y);
}
} points[N];
long long control[N], dist[N][N], total;
int n, m;
bool Check(long long d) {
Links::Init(n);
for (int i = 1; i <= n; ++ i) {
int rowh = -1;//防止把第一行的列表改了
for (int j = 1; j <= n; ++ j) {
if (dist[i][j] <= d) {
Links::Add(i, j, rowh);
}
}
}
Links::dfs(0);
return Links::ans <= m;
}
int main() {
int test;
scanf("%d", &test);
for (int t = 1; t <= test; ++ t) {
printf("Case #%d: ", t);
scanf("%d%d", &n, &m);
for (int i = 1; i <= n; ++ i) {
scanf("%d%d", &points[i].x, &points[i].y);
}
std::vector<long long> dists;
for (int i = 1; i <= n; ++ i) { //这里要注意距离为0的点也要加到距离数组里,之前就是忘记了
for (int j = i; j <= n; ++ j) {
dist[i][j] = dist[j][i] = points[i].Dist(points[j]);
dists.push_back(dist[i][j]);
}
}
std::sort(dists.begin(), dists.end());//别忘了排序
dists.resize(unique(dists.begin(), dists.end()) - dists.begin());
int lower = 0, upper = dists.size() - 1;
while (lower < upper) {
int middle = lower + upper >> 1;
if (Check(dists[middle])) {
upper = middle;
} else {
lower = middle + 1;
}
}
printf("%I64d\n", dists[lower]); // TO BE FIXED 注意这里返回的是下标,不是距离
}
return 0;
}
我的丑代码:
#include <cstdio>
#include <cstring>
#include <iostream>
#include <cmath>
#include <algorithm>
#include <climits>
using namespace std;
const int N=100;
const int M=N*N;
int t,n,k;
const int INF=0x3f3f3f3f;
int R[M],L[M],U[M],D[M];
int S[M];
long long l[M];
int col[M],row[M];
int size;//点数
int cnt;
int ans;
//int addnum[N],total;
long long dis[N][N];
struct Edge
{
long long x,y;
} E[N];
void init()
{
memset(S, 0, sizeof(S));
for (int i = 1; i <= n; ++ i)
{
R[i - 1] = L[i + 1] = U[i] = D[i] = i;
}
R[n] = 0;
L[0] = n;
size = n + 1;
ans = INT_MAX;
}
void add(int i,int x,int &rowh)
{
D[U[x]] = size;
U[size] = U[x];
D[size] = x;
U[x] = size;
S[x] ++;
row[size] = i;
col[size] = x;
if (rowh == -1)
{
L[size] = R[size] = size;
rowh = size;
}
else
{
R[size] = rowh;
L[size] = L[rowh];
R[L[rowh]] = size;
L[rowh] = size;
}
size ++;
}
void deal(long long s)
{
int i,j;
for(i=1; i<=n; i++)
{
int rowh=-1;
for(j=1; j<=n; j++)
if(dis[i][j]<=s) add(i,j,rowh);
}
}
void remove(int &c)
{
int i;
for(i=D[c]; i!=c; i=D[i])
{
L[R[i]]=L[i];R[L[i]]=R[i];
//cout<<"re"<<endl;
}
}
void resume(int &c)
{
int i;
for(i=U[c]; i!=c; i=U[i])
{
L[R[i]]=i;R[L[i]]=i;
}
}
int h()
{
bool ha[N];
memset(ha,false,sizeof(ha));
int ret=0;
int c;
for(c=R[0]; c!=0; c=R[c])
{
if(!ha[c])
{
ret++;
ha[c]=true;
for(int i=D[c]; i!=c; i=D[i])
for(int j=R[i]; j!=i; j=R[j])
ha[col[j]]=true;
}
}
return ret;
}
void dfs(int deep)
{
if(deep+h()>=ans) return ;
if(R[0]==0)
{
ans=min(ans,deep);
return ;
}
int idx,i,j,minnum=0x3f3f3f3f;
for(i=R[0]; i!=0; i=R[i])
if(S[i]<minnum) minnum=S[i],idx=i;
for(i=D[idx]; i!=idx; i=D[i])
{
remove(i);
for(j=R[i]; j!=i; j=R[j]) remove(j);
dfs(deep+1);
for(j=L[i]; j!=i; j=L[j]) resume(j);
resume(i);
}
return ;
}
long long mabs(long long x,long long y)
{
if(x>y) return x-y;
else return y-x;
}
void pre()
{
int i,j;
for(i=1; i<=n; i++)
for(j=i; j<=n; j++)
{
l[cnt++]=dis[i][j]=dis[j][i]=mabs(E[i].x,E[j].x)+mabs(E[i].y,E[j].y);
}
sort(l,l+cnt);
// for(i=0;i<cnt;i++) printf(" %I64d ",l[i]);printf("\n");
}
bool ok(long long s)
{
int i,j;
init();
deal(s);
dfs(0);
if(ans>k) return false;
else return true;
}
int bir()
{
int left=0,right=cnt-1,mid;
while(left<right)
{
// cout<<"left = "<<left<<" "<<right<<endl;
mid=(left+right)>>1;
long long distance=l[mid];
if(ok(distance)) right=mid;
else left=mid+1;
}
return left;
}
int ca=1;
int main()
{
//freopen("in","r",stdin);
scanf("%d",&t);
while(t--)
{
printf("Case #%d: ",ca++);
scanf("%d %d",&n,&k);
int i;
cnt=0;
for(i=1; i<=n; i++)
scanf("%I64d %I64d",&E[i].x,&E[i].y);
pre();
printf("%I64d\n",l[bir()]);
}
return 0;
}