poj-openjudge 1040:Bamboo Forest of the Lost 解题报告

题目

2013北大校赛

题意:

有一片竹林,分为n个区域,每个区域有k个状态,可能互不相同,但是总的状态数只有sk个。时间每过1单位所有区域的状态都会变化,周而复始,每个区域的变化顺序都会告诉你。

区域间有m条无向边,每条边连接u和v,行走时间花费是d(e),精力花费floor(w(e)×f(p(u,i),p(v,j))),其中p(u,i)是从u出发时u的状态,p(v,j)是到达v时v的状态,f是一个给定的矩阵,矩阵值是任意两个状态间的参数,w(e)是这条边的另一个参数。

在一个区域内也可以不走,花费c(i)精力可以在区域内度过1单位的时间。

现在进入区域1,走到区域n的最少精力?


解法:

重新建图,每个区域拆成k个点,由于原边花费时间是确定的,所以从u的什么状态出发,到达的v的状态也是确定,也就是知道花费的精力,所以新边权为花费的精力。同区域的点间按顺序也连上边权为c(i)的边。

最后跑最短路就行了。


RE了一次,因为某个vi[to[i]]写成了vi[i],光荣越界T_T

Time:350ms
Memory:6100kB
Length:2080 B
#include <iostream>
#include <cstdio>
#include <queue>
#include <cmath>
#include <cstring>
#include <algorithm>
#define EPS 1e-3
#define MAXN 100010
#define MAXM 4000005
#define INF 1000000007
#define MOD 1000000007
using namespace std;
int he[MAXN],to[MAXM],nex[MAXM],co[MAXM],top;
int yinshe[MAXN][11];
double f[30][30];
int dis[MAXN];
bool vi[MAXN];
void add(int u,int v,int w)
{
    if(u==v)    return ;
    to[top]=v;
    nex[top]=he[u];
    co[top]=w;
    he[u]=top++;
}
void SPFA(int k)
{
    queue<int> que;
    memset(vi,0,sizeof(vi));
    memset(dis,0x3f,sizeof(dis));
    dis[0]=0;
    que.push(0);
    while(que.size())
    {
        int now=que.front();
        que.pop();
        vi[now]=0;
        for(int i=he[now];i!=-1;i=nex[i])
            if(dis[to[i]]>dis[now]+co[i])
            {
                dis[to[i]]=dis[now]+co[i];
                if(!vi[to[i]])
                    vi[to[i]]=1,que.push(to[i]);
            }
    }
}
int main()
{
    //freopen("C:\\Documents and Settings\\k99\\My Documents\\input.txt","r",stdin);
    int t,n,m,k,sk,ans;
    scanf("%d",&t);
    while(t--)
    {
        scanf("%d%d%d%d",&n,&m,&k,&sk);
        memset(he,-1,sizeof(he));
        top=0;
        for(int i=0;i<n;++i)
        {
            int tmp;
            scanf("%d",&tmp);
            for(int j=0;j<k;++j)
                scanf("%d",&yinshe[i][j]),add(i*k+j,i*k+(j+1)%k,tmp);
        }
        for(int i=0;i<sk;++i)
            for(int j =0;j<sk;++j)
                scanf("%lf",&f[i][j]);
        for(int i=0;i<m;++i)
        {
            int u,v,w,d;
            scanf("%d%d%d%d",&u,&v,&w,&d);
            for(int j=0;j<k;++j)
                add((u-1)*k+j,(v-1)*k+(j+d)%k,(int)floor(w*f[yinshe[u-1][j]-1][yinshe[v-1][(j+d)%k]-1]));
                //cout<<(w*f[yinshe[u-1][j]-1][yinshe[v-1][(j+d)%k]-1])<<endl;
        }
        SPFA(k);
        ans=INF;
        for(int i=0;i<k;++i)
            ans=min(ans,dis[(n-1)*k+i]);
        printf("%d\n",ans);
    }
    return 0;
}


你可能感兴趣的:(poj-openjudge 1040:Bamboo Forest of the Lost 解题报告)