ZZU第四届程序设计大赛 6-三国志

http://acm.nyist.net/JudgeOnline/problem.php?pid=203

做了一上午的01背包,快中午的时候想到了这道题,最短路加01背包,思路很简单,但是runtime error和wa了几次

runtime time原因是数组开小了,但是我现在还不明白为嘛要那么大!!!wa是因为一个小陷阱:可能同两个城市之间有多个数据,要取最短的,而我默认的是后面输入的覆盖前面输入的;这样的陷阱以后需要注意!!!

代码如下:

#include<iostream>
#include<cstdio>
#include<cstring>
#include<cmath>
using namespace std;
#define INT_MAX 50000

int S, N, M;
int arcs[155][155];
int flag[155];
int path[155];
int val[155];
int result[100005]; //刚开始这个数组开小了,一直runtime error

int minpath(int min)
{
int i, mink;
mink = 0;
for(i = 1; i <= N; i++)
{
if(!flag[i])
{
if(path[i] <= min)
{
min = path[i];
mink = i;
}
}
}
return mink;
}

int main()
{
int tcases, i, j, a, b, dis, k, min;
scanf("%d", &tcases);
while(tcases--)
{
scanf("%d%d%d", &S, &N, &M);
for(i = 0; i <= N; i++)
for(j = 0; j <= N; j++)
if(i == j)
arcs[i][j] = 0;
else
arcs[i][j] = INT_MAX;
for(i = 0; i < M; i++)
{
scanf("%d%d%d", &a, &b, &dis);
if(arcs[a][b] > dis) //有输入陷阱。重复输入时取最小的
arcs[a][b] = arcs[b][a] = dis;
}
for(i = 1; i <= N; i++)
{
scanf("%d", &val[i]);
}
memset(flag, 0, sizeof(flag)); //dj最短路径
flag[0] = 1;
for(i = 1; i <= N; i++)
{
path[i] = arcs[0][i];
}
for(i = 1; i <= N; i++)
{
min = INT_MAX;
k = minpath(min);
flag[k] = 1;
for(j = 1; j <= N; j++)
{
if(!flag[j] && path[k] != INT_MAX && arcs[k][j] != INT_MAX && path[k] + arcs[k][j] < path[j])
path[j] = path[k] + arcs[k][j];
}
}
memset(result, 0, sizeof(result)); //01背包
for(i = 1; i <= N; i++)
{
for(j = S; j >= path[i]; j--)
{
if(result[j] < result[j-path[i]] + val[i])
result[j] = result[j-path[i]] + val[i];
}
}
printf("%d\n", result[S]);
}
return 0;
}

 

posted @ 2012-03-04 13:30  枫萧萧  阅读(316)  评论(0编辑  收藏  举报