ACM 题目求解 TLE了

gqjjqg 2009-10-19 08:00:53
描述:
在二维坐标上给你M个点(M是偶数)的坐标,坐标都是整数,你可以任意联接其中两点(不管中间有没有障碍),这两点就消失了(和游戏里的一样).但消去两点的路径和两个点的位置有关,也就是说路径的长度等于两点X轴与Y轴差的绝对值之和.比如一个点坐标为(10,10),另外一个点坐标为(2,3),那么消去这两个点的路径长度为8+7=15.问消去所有点的路径长度之和最小值是多少?

第一行输一个正整数N,下面有N种连连看的地图

每种地图的第一行输入一个正整数M
(M是偶数,并且2=< M <=20),代表地图上有M个点.
下面有M行,每一行都有两个整数,代表这个点的X轴坐标与Y轴坐标.
(坐标的绝对值不会大于十万)

输出共N行,每行都是消去所有点的路径长度之和的最小值.

Sample Input
3

2
10 10
2 3

2
0 1
0 2

4
0 2
0 3
0 5
0 6

Sample Output
15
1
2

-------------------------
我的方法 :

#include <stdio.h>
struct Point
{
int x, y;
}PointList[21];
int g_nSatusList[1024][1024];
int g_nPointList[21][21];
int g_nFlagList[21] = {0};
int n = 0;
int valuex = 1023, valuey = 1023;
int max1 = 0, max2 = 0;
int abs(int argA, int argB)
{
return argA > argB ? argA - argB : argB - argA;
}
int DeepInto(int Limit)
{
int i = 0 ,j = 0;
if (Limit == 2)
{
int x = -1, y = -1;
for (i = 0; i < n; i++)
{
if (g_nFlagList[i] == 0)
{
if (x == -1)
x = i;
else
y = i;
}
}
return g_nPointList[x][y] == 0 ? g_nPointList[y][x] : g_nPointList[x][y];
}
int minitemp = 200000000;
int tpj = -1;
for (i = 0; i < n; i++)
{
if (g_nFlagList[i] == 0)
{
if (tpj == -1)
tpj = i; //记录开始点
g_nFlagList[i] = 1;

if (i < 10)
valuex = (valuex ^ (1 << i));
else
valuey = (valuey ^ (1 << (i - 10)));

int j = 0;
for (j = tpj; j < n; j++)
{
if (g_nFlagList[j] == 0 && minitemp > g_nPointList[i][j])
{
g_nFlagList[j] = 1;

if (j < 10)
valuex = (valuex ^ (1 << j));
else
valuey = (valuey ^ (1 << (j - 10)));

int temp;

if (g_nSatusList[valuex][valuey] != -1)
{
temp = g_nSatusList[valuex][valuey];
}
else
{
temp = DeepInto(Limit - 2);
}
int ijLength = g_nPointList[i][j] == 0 ? g_nPointList[j][i] : g_nPointList[i][j];
if (minitemp > ijLength + temp)
{
minitemp = ijLength + temp;
}

if (g_nSatusList[valuex][valuey] == -1 ||
g_nSatusList[valuex][valuey] > minitemp)
g_nSatusList[valuex][valuey] = minitemp;
g_nFlagList[j] = 0;

if (j < 10)
valuex = (valuex ^ (1 << j));
else
valuey = (valuey ^ (1 << (j - 10)));
}
}
g_nFlagList[i] = 0;
if (i < 10)
valuex = (valuex ^ (1 << i));
else
valuey = (valuey ^ (1 << (i - 10)));
}
}
return minitemp;
}
void initailArray(int MX, int MY)
{
int i = 0, j = 0;
for (;i < MX; i++)
for(j = 0; j < MY; j++)
g_nSatusList[i][j] = -1;
}
int main ()
{
int CaseN = 0;
while (1 == scanf("%d", &CaseN))
{
while (CaseN--)
{
scanf("%d", &n);
int i = n;
max1 = 0, max2 = 0;
while (i--)
{
scanf("%d %d", &PointList[i].x, &PointList[i].y);
if (i < 10)
max1 = max1 | (1 << i);
else
max2 = max2 | (1 << (i - 10));
}
i = n;
while (i--)
{
int j = 0;
while (j < i)
{
g_nPointList[i][j] = abs(PointList[i].x, PointList[j].x) +
abs(PointList[i].y, PointList[j].y);
j++;
}
}
i = n;
initailArray(max1 + 1, max2 + 1);
valuex = max1, valuey = max2;
printf("%d\n", DeepInto(i));
}
}
return 0;
}


20 个点的数据的时候 要大概3S左右:
例如这组
20
1 2
1000 1
1000 2
3 5
8 11111
222 156
123 123
125 159
11111 12
2101 23
15687 1264
456 4561
121 2315
1 123
1 3
2 56
6 98
9000 12
6000 112
2 1111
求高手解答..代码基本无注释,不好意思..
我的思路:穷举搜索的话 次数超多死T,T的原因应该是 很多组数据时重复在做的,所以,我用一个 二维数组保存做过的 组合,减少重复量,不过我能做的也就这么多....还是不行,20个点搜索 还是要 3S 多...

...全文
243 18 打赏 收藏 转发到动态 举报
写回复
用AI写文章
18 条回复
切换为时间正序
请发表友善的回复…
发表回复
gqjjqg 2009-10-22
  • 打赏
  • 举报
回复
没人愿意帮忙解决下么?..晕
wanjingwei 2009-10-20
  • 打赏
  • 举报
回复
等待强人
gqjjqg 2009-10-20
  • 打赏
  • 举报
回复
哎....等待强人给个详解..
morilasi 2009-10-20
  • 打赏
  • 举报
回复
[Quote=引用 6 楼 limzi 的回复:]
ACM的题,很少能用穷取解的……

用动态规划吧
[/Quote]剪枝做的好。有时候也是可以的。
顺便弱弱问下,这个题,DP你有啥思路么?
limzi 2009-10-20
  • 打赏
  • 举报
回复
ACM的题,很少能用穷取解的……

用动态规划吧
morilasi 2009-10-20
  • 打赏
  • 举报
回复
同Mark,看有什么好的算法。。
gqjjqg 2009-10-20
  • 打赏
  • 举报
回复
[Quote=引用 3 楼 whg01 的回复:]
MARK 表示“关注中”。
[/Quote]
汗......ing
delphiwcdj 2009-10-20
  • 打赏
  • 举报
回复
[Quote=引用 4 楼 gqjjqg 的回复:]
引用 3 楼 whg01 的回复:
MARK 表示“关注中”。

汗......ing
[/Quote]
Notice,attention
whg01 2009-10-20
  • 打赏
  • 举报
回复
MARK 表示“关注中”。
gqjjqg 2009-10-20
  • 打赏
  • 举报
回复
[Quote=引用 1 楼 whg01 的回复:]
MARK
[/Quote]
标记? 解释下啊?
gqjjqg 2009-10-20
  • 打赏
  • 举报
回复
[Quote=引用 14 楼 pcboyxhy 的回复:]
引用 13 楼 gqjjqg 的回复:
引用 12 楼 pcboyxhy 的回复:
并且2=  < M  <=20,一看这数据范围就知道,肯定是很暴力的解法,
搜索的肯定的,搜索的过程中可以做些优化,减少不必要的重复计算。
你可以记录些中间结果,对小规模的数据打表,避免大量的重复计算。
保存中间结果的递归,也可以利用dp思想,转化为迭代,减少函数调用开销。


我的思路应该差不多,不过 DP 想不出......
能给我个更进一步的思路就好了..


dist[20][20][20][20],记录下4个点的最优解,再次遇到的时候,就不用重复计算了
[/Quote]


我晕..差不多也用了3S左右 ....我昏倒了...请告诉我具体解决方法吧..我怕是不行了....
gqjjqg 2009-10-20
  • 打赏
  • 举报
回复
额...我再去试试..
pcboyxhy 2009-10-20
  • 打赏
  • 举报
回复
[Quote=引用 13 楼 gqjjqg 的回复:]
引用 12 楼 pcboyxhy 的回复:
并且2= < M <=20,一看这数据范围就知道,肯定是很暴力的解法,
搜索的肯定的,搜索的过程中可以做些优化,减少不必要的重复计算。
你可以记录些中间结果,对小规模的数据打表,避免大量的重复计算。
保存中间结果的递归,也可以利用dp思想,转化为迭代,减少函数调用开销。


我的思路应该差不多,不过 DP 想不出......
能给我个更进一步的思路就好了..
[/Quote]

dist[20][20][20][20],记录下4个点的最优解,再次遇到的时候,就不用重复计算了
gqjjqg 2009-10-20
  • 打赏
  • 举报
回复
[Quote=引用 12 楼 pcboyxhy 的回复:]
并且2= < M <=20,一看这数据范围就知道,肯定是很暴力的解法,
搜索的肯定的,搜索的过程中可以做些优化,减少不必要的重复计算。
你可以记录些中间结果,对小规模的数据打表,避免大量的重复计算。
保存中间结果的递归,也可以利用dp思想,转化为迭代,减少函数调用开销。
[/Quote]

我的思路应该差不多,不过 DP 想不出......
能给我个更进一步的思路就好了..
pcboyxhy 2009-10-20
  • 打赏
  • 举报
回复
并且2= < M <=20,一看这数据范围就知道,肯定是很暴力的解法,
搜索的肯定的,搜索的过程中可以做些优化,减少不必要的重复计算。
你可以记录些中间结果,对小规模的数据打表,避免大量的重复计算。
保存中间结果的递归,也可以利用dp思想,转化为迭代,减少函数调用开销。
gqjjqg 2009-10-20
  • 打赏
  • 举报
回复
[Quote=引用 10 楼 mtttt 的回复:]
哎呀,要去上课了。。。。。LZ,你参加acm比赛的吗?有没得奖啊?
[/Quote]

参加过,我是作现场工作人员,哈哈哈
说实话,自己实力太弱,没办法....
其实自己慢慢摸索成长不也挺好的么?
mtttt 2009-10-20
  • 打赏
  • 举报
回复
哎呀,要去上课了。。。。。LZ,你参加acm比赛的吗?有没得奖啊?
whg01 2009-10-19
  • 打赏
  • 举报
回复
MARK

69,378

社区成员

发帖
与我相关
我的任务
社区描述
C语言相关问题讨论
社区管理员
  • C语言
  • 花神庙码农
  • 架构师李肯
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
暂无公告

试试用AI创作助手写篇文章吧