HDU 1158

AC自动机中的DP

  1 #include <iostream>
  2 #include <cstdio>
  3 #include <cstring>
  4 #include <string.h>
  5 #include <string>
  6 #include <queue>
  7 #include <map>
  8 using namespace std;
  9 const int N=52*2;
 10 char str[52],s1[52];
 11 map<char,int> map1;
 12 int ch[N][52],fail[N],val[N],sz,root,n;
 13
 14 struct BigInt{
 15     int v[100],len;
 16     BigInt(int t=0){
 17         memset(v,0,sizeof(v));
 18         for(len=0;t>0;t/=10){
 19             v[len++]=t%10;
 20         }
 21     }
 22     BigInt operator + (const BigInt &a){
 23         BigInt ans;
 24         int i,c=0;
 25         for(i=0;i<a.len||i<len||c>0;i++){
 26             if(i<len)c+=v[i];
 27             if(i<a.len)c+=a.v[i];
 28             ans.v[i]=c%10;
 29             c/=10;
 30         }
 31         ans.len=i;
 32         return ans;
 33     }
 34     void print(){
 35         if(len==0)printf("0\n");
 36         else {
 37             for(int i=len-1;i>=0;i--){
 38                 printf("%d",v[i]);
 39             }
 40         printf("\n");
 41         }
 42     }
 43 }dp[52][N];
 44
 45
 46 int newnode(){
 47     memset(ch[sz],-1,sizeof(ch[sz]));
 48     val[sz]=0;
 49     return sz++;
 50 }
 51 void init(){
 52     sz=0;
 53     root=newnode();
 54 }
 55 void  insert(char* str1){
 56     int len=strlen(str1);
 57     int now=root;
 58     for(int i=0;i<len;i++){
 59         int &tem=ch[now][map1[str1[i]]];
 60         if(tem==-1){
 61             tem=newnode();
 62         }
 63         now=tem;
 64     }
 65     val[now]=1;
 66 }
 67
 68
 69 void getfail(){
 70     queue<int> q;
 71     fail[root]=root;
 72     for(int i=0;i<n;i++){
 73         int &u=ch[root][i];
 74         if(u==-1)u=root;
 75         else {
 76             fail[u]=root;
 77             q.push(u);
 78         }
 79     }
 80     while(!q.empty()){
 81         int now=q.front();
 82         q.pop();
 83         for(int i=0;i<n;i++){
 84             if(ch[now][i]==-1){
 85                 ch[now][i] = ch[fail[now]][i];
 86             }
 87             else{
 88                 fail[ch[now][i]]=ch[fail[now]][i];
 89                 val[ch[now][i]]+=val[fail[ch[now][i]]];
 90                 q.push(ch[now][i]);
 91             }
 92         }
 93     }
 94 }
 95 void getsum(int l){
 96     for(int i=0;i<52;i++){
 97         for(int j=0;j<sz;j++)dp[i][j]=BigInt();
 98     }
 99     dp[0][root] = BigInt(1);
100     for(int i=0;i<l;i++){
101         for(int j=0;j<sz;j++){
102             if(val[j])continue;
103             for(int k = 0;k <n;k++){
104                 if(val[ch[j][k]])continue;
105                 dp[i+1][ch[j][k]] = dp[i+1][ch[j][k]]+dp[i][j];
106             }
107         }
108     }
109     BigInt ans;
110     for(int i=0;i<sz;i++)
111         ans = ans + dp[l][i];
112     ans.print();
113 }
114 int main(){
115     int m,p;
116     scanf("%d%d%d",&n,&m,&p);
117     getchar();
118     scanf("%s",str);
119     for(int i=0;i<n;i++){
120         map1[str[i]]=i;
121     }
122     init();
123     for(int i=0;i<p;i++){
124         scanf("%s",s1);
125         insert(s1);
126     }
127     getfail();
128     getsum(m);
129     return 0;
130
131 }

HDU 1158

时间: 2024-10-15 02:12:30

HDU 1158的相关文章

HDU 1158 Employment Planning (DP)

Problem Description A project manager wants to determine the number of the workers needed in every month. He does know the minimal number of the workers needed in each month. When he hires or fires a worker, there will be some extra cost. Once a work

HDU 1158 Employment Planning

题意:有一公司要工作n个月每个月需要至少p[i]个人工作,每个人的工资固定位m, 每雇佣一个人要花费h,每炒掉一个人要花费f.求完成n个月工作,公司最小的花费. 思路: Dp[i][j]为前i个月的留j个人的最优解;p[i]<=j<=Max{p[i]}; j>Max{p[i]}之后无意义,无谓的浪费 记Max_n=Max{p[i]}; Dp[i-1]中的每一项都可能影响到Dp[i],即使p[i-1]<<p[i] 所以利用Dp[i-1]中的所有项去求Dp[i]; 对于p[i]&

Hdu 1158 Employment Planning(DP)

Problem地址:http://acm.hdu.edu.cn/showproblem.php?pid=1158 一道dp题,或许是我对dp的理解的还不够,看了题解才做出来,要加油了. 只能先上代码了. #include <iostream> #include <cstring> #include <cstdio> using namespace std; const int MAXN = 100 + 28; int dp[15][MAXN]; int workers[

hdu 1158(dp)

题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=1158 Employment Planning Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 65536/32768 K (Java/Others) Total Submission(s): 3654    Accepted Submission(s): 1502 Problem Description A project manage

C语言动态规划(8)___雇佣工人(HDU 1158)

Problem Description A project manager wants to determine the number of the workers needed in every month. He does know the minimal number of the workers needed in each month. When he hires or fires a worker, there will be some extra cost. Once a work

hdu 1158 dp

1 /* 2 题目大意:给n个月工作需要的人数,雇佣一个需要花hire 3 每个月的薪水是salary,解雇一个需要fire 4 求完成所有工作的最小费用 5 dp(i,j)表示第i个月雇佣j员工的最小费用 6 */ 7 #include <iostream> 8 #include <cstdio> 9 #include <cstring> 10 using namespace std; 11 12 const int maxn=15; 13 const int INF

HDU 1158 Employment Planning【DP】

题意:给出n个月,雇佣一个人所需的钱hire,一个人工作一个月所需要的钱salary,解雇一个人所需要的钱fire,再给出这n个月每月1至少有num[i]个人完成工作,问完成整个工作所花费的最少的钱是多少. 用dp[i][j]表示在第i个月雇佣j个人所需要的最少花费 先考虑只解雇人和聘请人的情况 1 for(j=num[i];j<=sum;j++) 2 { 3 if(j>num[i-1])//说明雇佣了人 4 dp[i][j]=dp[i-1][num[i-1]]+j*salary+(j-num

hdu 1158 Employment Planning(DP)

题意: 有一个工程需要N个月才能完成.(n<=12) 给出雇佣一个工人的费用.每个工人每个月的工资.解雇一个工人的费用. 然后给出N个月所需的最少工人人数. 问完成这个项目最少需要花多少钱. 思路: 将(i,num):[第i个月拥有num个工人 ]看成一个状态.那么就想到用DP. 看代码 代码: struct node{ int minNum, maxNum; } month[15]; int n; int hire,salary,fire; int dp[15][505]; int main(

HDU 1158【简单dp】

题意:给你一个项目,需要几个月来完成买,同时也给你每个月最少需要的工人数.并且告诉你hiring,firing每个工人的钱数,以及每个月应付每个工人的工资.求项目完成时最小花费. 这是个简单dp,思路就是枚举一下上一个月和本月的工人数,写个状态转移方程即可. #include<stdio.h> #include<string.h> #include<queue> #include<iostream> #define MAX 6000 #define INF