zoukankan      html  css  js  c++  java
  • AGC017 F

    传送门

    Time limit : 4sec / Memory limit : 256MB

    Score : 1600 points

    Problem Statement

    There are N(N+1)2 dots arranged to form an equilateral triangle whose sides consist of N dots, as shown below. The j-th dot from the left in the i-th row from the top is denoted by (i,j) (1iN, 1ji). Also, we will call (i+1,j) immediately lower-left to (i,j), and (i+1,j+1) immediately lower-right to (i,j).

    Takahashi is drawing M polygonal lines L1,L2,…,LM by connecting these dots. Each Li starts at (1,1), and visits the dot that is immediately lower-left or lower-right to the current dots N1 times. More formally, there exist Xi,1,…,Xi,N such that:

    • Li connects the N points (1,Xi,1),(2,Xi,2),…,(N,Xi,N), in this order.
    • For each j=1,2,…,N1, either Xi,j+1=Xi,j or Xi,j+1=Xi,j+1 holds.

    Takahashi would like to draw these lines so that no part of Li+1 is to the left of Li. That is, for each j=1,2,…,N, X1,jX2,jXM,j must hold.

    Additionally, there are K conditions on the shape of the lines that must be followed. The i-th condition is denoted by (Ai,Bi,Ci), which means:

    • If Ci=0, LAi must visit the immediately lower-left dot for the Bi-th move.
    • If Ci=1, LAi must visit the immediately lower-right dot for the Bi-th move.

    That is, XAi,Bi+1=XAi,Bi+Ci must hold.

    In how many ways can Takahashi draw M polygonal lines? Find the count modulo 1000000007.

    Notes

    Before submission, it is strongly recommended to measure the execution time of your code using "Custom Test".

    Constraints

    • 1N20
    • 1M20
    • 0K(N1)M
    • 1AiM
    • 1BiN1
    • Ci=0 or 1
    • No pair appears more than once as (Ai,Bi).

    Input

    Input is given from Standard Input in the following format:

    N M K
    A1 B1 C1
    A2 B2 C2
    :
    AK BK CK
    

    Output

    Print the number of ways for Takahashi to draw M polygonal lines, modulo 1000000007.

    Sample Input 1

    3 2 1
    1 2 0
    

    Sample Output 1

    6
    

    There are six ways to draw lines, as shown below. Here, red lines represent L1, and green lines represent L2.

    Sample Input 2

    3 2 2
    1 1 1
    2 1 0
    

    Sample Output 2

    0

    Sample Input 3

       5 4 2

       1 3 1

       4 2 0

    Sample Output 3

    172

    Sample Input 4

    20 20 0
    

    Sample Output 4

    881396682

    题目大意
    有一高度为N的三角形,共有M条线从顶部走到底部,要求第L+1条线不能在第L条线的左边,有K个要求,要求第a条线必须在第b层向某方向走(c为一即向左,为二则向右),问共有几种情况

    代码
    #include<iostream>

    #include<cstdio>
    #include<cstring>
    #include<string>
    #include<algorithm>
    #include<cctype>
    #include<cmath>
    #include<cstdlib>
    #include<queue>
    #include<ctime>
    #include<vector>
    #include<set>
    #include<map>
    #include<stack>
    using namespace std;
    int dp[1048580];
    int need1[21],need2[21];
    int put[1048580],go[1048580][21];
    //go是记录将一条先向左再向右边翻折后的形状
    //put记录自下向上找,第一个向左的边
    int n,m,k;
    int main()
    {     int i,j,p,q,a,b,c;
          scanf("%d%d%d",&n,&m,&k);
          for(i=1;i<=k;i++){
              scanf("%d%d%d",&a,&b,&c);
              a--,b--;
              need1[a]|=(1<<b);
              need2[a]|=(1<<b)*c;
    //必须走的路径

          }
          n--;
          memset(go,-1,sizeof(go));
          memset(put,-1,sizeof(put));
          for(i=0;i<(1<<n);i++){
               int num=0;
             for(j=0;j<n;j++)
                if(i&(1<<j)){
                  if(j>0&&!(i&(1<<(j-1)))){
                    go[i][num]=i^(1<<j)^(1<<(j-1));
    //i指路径,num指是第几个向右的边
                  }
                  num++;
                }
          }
          for(i=0;i<(1<<n);i++)
             for(j=n-1;j>=0;j--){
                if((i&(1<<j)))continue;
                put[i]=i^(1<<j);
                break;
             }
          dp[0]=1;
          for(i=0;i<m;i++){
             for(j=0;j<(1<<n);j++)
                if(put[j]){
                  dp[put[j]]+=dp[j];
                  dp[put[j]]%=1000000007;
             }
             for(p=0;p<n;p++)
                for(j=(1<<n)-1;j>=0;j--)
                   if(go[j][p]!=-1){
                     dp[go[j][p]]+=dp[j],
                     dp[go[j][p]]%=1000000007;
                   }
             for(j=0;j<(1<<n);j++)
                if((j&need1[i])!=need2[i])
                  dp[j]=0;
          }
          int ans=0;
          for(i=0;i<(1<<n);i++)
             ans+=dp[i],
             ans%=1000000007;
          printf("%d ",ans%1000000007);
          return 0;
    }
  • 相关阅读:
    win8及win8.1商店出现0X80073CF9的解决办法!
    Ubuntu 14.04 登陆界面循环问题解决
    Java学习笔记-Json
    Java学习笔记-Thread-线程
    git学习笔记
    Java学习笔记-File
    java学习笔记-set
    C# 实验4 数据库
    C#文件处理
    C#-实验3
  • 原文地址:https://www.cnblogs.com/yzxverygood/p/8446781.html
Copyright © 2011-2022 走看看