题目大意:给你一张道路情况的无权有向图,请你找出从a到b中途经过k个旅游景点的道路方案数,并且结果要模除1000。

解题思路:本题之前有做过一个类似的,只不过所求的解不同,那题是求最短路。这题则是用DP,设状态dp[k][j]表示从起点到达j位置,并且中途经过k个旅游景点的方案数,则状态转移方程:dp[k][z]=(dp[k][z]+dp[k-1][j])%1000,解释:从起点到达终点如果可以直接到达就为1,这里要初始化边界dp[0][b]=1,表示不用经过任何景点就能到达,状态转移就是从中插1个,然后2个,然后...最终到达最优解。并且在写转移方程要注意的点是:当起点j和终点z连通,才能够增加方法数,类似于分步乘法的组合数原理,每次多一种路的情况把之前的方法数加上来。(好吧我也不知道在讲啥了,思路有点乱,看代码吧,我想说得是你要知道终点和起点方法数的转移这点就对了)这里之前写有个bug,想当然地想打表减少复杂度,但是始终不知道在起点不同的情况下怎么处理,然后就英勇的gg了。

AC代码如下:

#include<stdio.h>
#include<string.h>
#include<iostream>
#include<algorithm>
using namespace std;

const int maxn=21;

int dp[maxn][maxn],map[maxn][maxn];

int main()
{
    int i,j,s,z,a,b,k,n,m;
    while(~scanf("%d%d",&n,&m) && n+m)
    {
        memset(map,0,sizeof(map));
        //无向图构建
        for(i=0;i<m;i++)
        {
            cin>>a>>b;
            map[a+1][b+1]=1;
        }
        cin>>s;
        while(s--)
        {
            memset(dp,0,sizeof(dp));
            scanf("%d%d%d",&a,&b,&k);
            dp[0][a+1]=1;
            for(i=1;i<=k;i++)
            {
                for(j=1;j<=n;j++)
                    for(z=1;z<=n;z++)
                        if(map[j][z])
                        {
                            dp[i][z]=(dp[i-1][j]+dp[i][z])%1000;
                        }
            }
            cout<<dp[k][b+1]<<endl;
        }
    }
    return 0;
}

好像网上的题解大多是矩阵快速幂的解法QAQ