题目:
http://acm.pku.edu.cn/JudgeOnline/problem?id=1062
//贪心(Dijkstra) + 枚举
#include <stdio.h>
#include <memory.h>
#define MAX_N 105
#define INF 1<<20
#define Min(x,y) ((x) < (y) ? (x) : (y))
int arcs[MAX_N][MAX_N];
int dist[MAX_N];
int level[MAX_N];
//访问标志,等级限制不能访问或者已经访问过的节点标记为1
int visit[MAX_N];
int M,N;
//visit : 1 <======> low <= level[i] <= upper
void init_visit(int low,int upper){
for(int i = 1;i <= N;i++)
if(low <= level[i] && level[i] <= upper)
visit[i] = 0;
else
visit[i] = 1;
}
//源点为N + 1
int Dijkstra(){
int i,k;
//初始化dist[]数组
for(i = 1;i <= N;i++)
dist[i] = arcs[N + 1][i];
dist[N + 1] = 0;
visit[N + 1] = 1;
//选择剩余的N个节点
for(k = 1;k <= N;k++){
int minDist = INF;
int u = -1;
//寻找下一个路径最短的点u
for(i = 1;i <= N;i++)
if(visit[i] == 0 && dist[i] <= minDist){
minDist = dist[i];
u = i;
}
//已经找到到1节点的最短距离
if(u == 1)
return dist[1];
//加入u到已经找到的点的集合中
visit[u] = 1;
//更新dist[]数组距离
for(i = 1;i <= N;i++)
if(visit[i] == 0 && dist[u] + arcs[u][i] < dist[i])
dist[i] = dist[u] + arcs[u][i];
}
return dist[1];
}
int main(){
int i,j;
int P,L,X;
int T,V;
//逆向建有向图.从替代品到原物品有边,权为优惠价格
//从源点--N + 1到各个节点都有边,权为物品价格
FILE *fp = fopen("1062.txt","r");
while(scanf("%d%d",&M,&N)/* fscanf(fp,"%d%d",&M,&N)*/!= EOF){
for(i = 1;i <= N;i++)
for(j = 1;j <= N;j++)
if(i == j)
arcs[i][j] = 0;
else
arcs[i][j] = INF;
for(i = 1;i <= N;i++){
scanf("%d%d%d",&P,&L,&X);
//fscanf(fp,"%d%d%d",&P,&L,&X);
arcs[N + 1][i] = P;
level[i] = L;
for(j = 1;j <= X;j++){
scanf("%d%d",&T,&V);
//fscanf(fp,"%d%d",&T,&V);
arcs[T][i] = V;
}
}
/*
for(i = 1;i <= N + 1;i++){
for(j = 1;j <= N + 1;j++)
printf("%d/t",arcs[i][j]);
printf("/n");
}
*/
int mincost = INF,temp;
for(i = 0;i <= M;i++){
init_visit(level[1] - i,level[1] - i + M);
temp = Dijkstra();
mincost = Min(mincost,temp);
}
printf("%d/n",mincost);
}
return 0;
}