ZOJ 3644 Kitty's Game (广搜,STL中的map,vector)

本博客探讨了一个关于游戏场景计数的问题,玩家在不同场景间移动,分数通过最小公倍数(LCM)变化。通过使用map映射简化路径计算,实现高效搜索路径数量,最终输出在特定场景到达次数及分数。代码示例展示了如何解决此类问题。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

Kitty's Game

Time Limit: 2 Seconds      Memory Limit: 65536 KB

Kitty is a little cat. She is crazy about a game recently.

There are n scenes in the game(mark from 1 to n). Each scene has a number pi. Kitty's score will become least_common_multiple(x,pi) when Kitty enter the ith scene. x is the score that Kitty had previous. Notice that Kitty will become mad If she go to another scene but the score didn't change.

Kitty is staying in the first scene now(with p1 score). Please find out how many paths which can arrive at the nth scene and has k scores at there. Of course, you can't make Kitty mad.

We regard two paths different if and only if the edge sequence is different.

Input

There are multiple test cases. For each test case:

The first line contains three integer n(2 ≤ n ≤ 2000), m(2 ≤ m ≤ 20000), k(2 ≤ k ≤ 106). Then followed by m lines. Each line contains two integer u, v(1 ≤ u, v ≤ n, u ≠ v) indicate we can go to vth scene from uth scene directly. The last line of each case contains n integer pi(1 ≤ pi ≤ 106).

Process to the end of input.

Output

One line for each case. The number of paths module 1000000007.

Sample Input
5 6 84
1 2
2 5
1 3
3 5
1 4
4 5
1 5 4 12 21
Sample Output
2



此题比赛的时候没有想到方法。
赛后看题解恍然大悟。
用map映射可以很方便解决。
直接搜索就可以了。
具体看代码:
#include<stdio.h>
#include<vector>
#include<iostream>
#include<map>
#include<string.h>
#include<queue>
#include<algorithm>
using namespace std;

const int MAXN=2010;
const int MOD=1000000007;
vector<int>g[MAXN];
map<int,int>dp[MAXN];
int n,k;
int score[MAXN];
bool vis[MAXN];

int gcd(int a,int b)
{
    if(b==0)return a;
    return gcd(b,a%b);
}
int bfs()
{
    int ret=0;
    queue<int>q;
    dp[1][score[1]]=1;
    memset(vis,false,sizeof(vis));
    while(!q.empty())q.pop();
    q.push(1);
    vis[1]=true;
    while(!q.empty())
    {
        int cur=q.front();
        q.pop();
        vis[cur]=false;
        if(cur==n)ret=(ret+dp[cur][k])%MOD;
        for(int i=0;i<g[cur].size();i++)
        {
            int v=g[cur][i];
            map<int,int>::iterator it;
            for(it=dp[cur].begin();it!=dp[cur].end();it++)
            {
                int temp=it->first;
                int lcm=temp/gcd(temp,score[v])*score[v];
                if(lcm!=temp &&  k%lcm==0)
                {
                    dp[v][lcm]=(dp[v][lcm]+it->second)%MOD;
                    if(!vis[v])
                    {
                        vis[v]=true;
                        q.push(v);
                    }
                }
            }
        }
        dp[cur].clear();
    }
    return ret;
}
int main()
{
    int m,u,v;
    while(scanf("%d%d%d",&n,&m,&k)!=EOF)
    {
        for(int i=1;i<=n;i++)g[i].clear();
        for(int i=1;i<=n;i++)dp[i].clear();
        while(m--)
        {
            scanf("%d%d",&u,&v);
            g[u].push_back(v);
        }
        for(int i=1;i<=n;i++)scanf("%d",&score[i]);
        printf("%d\n",bfs());
    }
    return 0;
}

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值