Section 2.3 蔓延感

Longest Prefix

给定一堆小字符串,问最长可以组成给定的大字符串的多少位前缀。

类似于DP的思想,标记出结束位置。看最远结束在哪里。

#include <bits/stdc++.h>
using namespace std;
const int N  = 1205;
const int M  = 200004;
string ch[N];
char st[100];
bool ok[M];
int main()
{
    string str = "";
    string s;
    freopen("prefix.in","r",stdin);
    #ifndef poi
    freopen("prefix.out","w",stdout);
    #endif
    int id = 1;
    int i, j, k;
    cin >> st ;

    while(st[0] != '.') {
        ch[id] = (string)st;
       // cout << ch[id] << endl;
        id++;
        cin >> st;
    }
    id --;
    while(cin>>s) str += s;
    int len = str.length();
    ok[0] = true;
    int ans;
    for(i = 0;  i <= len; i++){
        if(!ok[i])continue;
        ans = i;
        for(j = 1; j <= id; j++){
            for(k = 0; ch[j][k] != '\0'&&j+k<=len; k++)   {
                if(str[i+k] != ch[j][k])  break;
            }
            if(ch[j][k]!='\0')  continue;
            ok[i+k] = true;
        }
    }
    cout <<ans<<endl;
    return 0;
}
View Code

 

Cow Pedigrees

每头牛要么不生,要么生两只。最多200只,问正好升到K代的族谱的可能性。

 

DP。

状态:DP[I][J]表示用I头牛最多到J代的族谱的可行方案数。

转移:DP[I][J]=ΣDP[K][J-1]*DP[I-K-1][J-1] (1<=K<=I-2)

  解释:可以视为再放一头牛当现有的祖先,则一边是左(K) 一边是右儿子(I-K-1) 

 

 1 #include <bits/stdc++.h>
 2 using namespace std;
 3 const int N = 204;
 4 
 5 const int MOD = 9901;
 6 int dp[N][N];
 7 int main()
 8 {
 9     freopen("nocows.in","r",stdin);
10     #ifndef poi
11     freopen("nocows.out","w",stdout);
12     #endif
13     int n, m, i, j, k;
14     cin >> n >> m;
15     for(i = 1; i <= m; i++)dp[1][i] = 1;
16     for(i = 2; i <= n; i++){
17         for(j = 1; j <= m; j++){
18             for(k = 1; k <= i - 2; k++){
19                 dp[i][j] =((dp[k][j-1]*dp[i-k-1][j-1])%MOD+dp[i][j])%MOD;
20             }
21         }
22     }
23     int ans = ((dp[n][m] - dp[n][m-1])%MOD+MOD)%MOD;
24     cout << ans<<endl;
25     return 0;
26 }
View Code

Zero Sum

1 2 3 4 5 。。。N 这样,可以在两个之间插+ - 和空格 ,问有多少种插法可以使得最后结果是0

DFS暴力搜索。

#include <bits/stdc++.h>
using namespace std;
char ans[50];

int n;
void dfs(int nowsum, int nowdig, int presum){

    //system("pause");
    if(nowdig == n){ //cout << nowsum << " "<<nowdig <<" " << presum<<endl;
        if(nowsum + presum== 0) {

            cout << ans << endl;
        }
        return;
    }
    ans[nowdig*2-1] = ' ';
    ans[nowdig<<1] = nowdig + 1 + '0';

    dfs(nowsum, nowdig + 1, presum*10+(nowdig + 1)*(presum<0?-1:1));

    ans[nowdig*2-1] = '+';
    ans[nowdig<<1] = nowdig + 1 + '0';
//    if(nowdig == 6){
//        cout << nowsum+presum<<" " <<nowdig+1<<" "<<  nowdig + 1<<endl;
//    }
    dfs(nowsum+presum, nowdig + 1, nowdig + 1);

    ans[nowdig*2-1] = '-';
    ans[nowdig<<1] = nowdig + 1 + '0';
    dfs(nowsum+presum, nowdig + 1, -nowdig -1);

}
int main()
{
    freopen("zerosum.in","r",stdin);
    #ifndef poi
    freopen("zerosum.out","w",stdout);
    #endif
    ans[0] = '1';

    cin >> n;
    ans[(n<<1)-1] = '\0';
    dfs(0, 1, 1);
       return 0;     
}
View Code

Money Systems

裸背包

#include <bits/stdc++.h>
using namespace std;
const int N = 30;
const int M = 10004;
typedef long long ll;

ll dp[M];
int val[N];
int main()
{
    freopen("money.in","r",stdin);
    #ifndef poi
    freopen("money.out","w",stdout);
    #endif
    int n, m, i, j;
    dp[0]= 1;
    cin >> n >> m;
    for(i = 1 ;i <= n; i++)cin >> val[i];

    for(i = 1; i <= n; i++){
        for(j = val[i]; j <= m; j++){
            dp[j]+= dp[j-val[i]];
        }
    }
    cout << dp[m]<< endl;

}
View Code

Controlling Companies

http://www.wzoi.org/usaco/13%5C309.asp 题意偷懒。。

我们可以感觉应该是一层一层往上推出来的。

所以可以用队列这样的感觉,每次发现了一个新的控制信息,就放进队列,待会儿更新控股信息。

#include <bits/stdc++.h>
using namespace std;
const int N = 104;

bool con[N][N];
int have[N][N];
struct point{
    int a, b;
    point(){};
    point(int _a, int _b){a = _a, b = _b;};
};
int main()
{
    freopen("concom.in","r",stdin);
    #ifndef poi
    freopen("concom.out","w",stdout);
    #endif
    queue<struct point>q;
    int n, a, b, c, m = 0, i, j;
    scanf("%d", &n);
    for(i = 1; i <= n; i++){
        scanf("%d%d%d", &a, &b, &c);
        m = max( m, b);        m = max(m, a);
       // cout << c <<endl;
        if(c>=50){
            con[a][b] = true;
            q.push(point(a, b));

        }
        have[a][b]+= c;
    }
  //  cout <<have[2][3]<<endl;
    point x;
    while(!q.empty()){
        x = q.front();
        a= x.a; b = x.b;
      //  cout << a << " "<< b << endl;
        q.pop();
        for(i = 1; i <= m; i++){
           // if(!con[b][i] ) continue;

            if(have[a][i] >= 50)    continue;
            have[a][i] += have[b][i];
        //    cout << a << "!" << i << " " << have[a][i] <<" " << have[b][i]<<endl;
            if(have[a][i] >= 50){
                con[a][i] = true;
                q.push(point(a, i));
            }
        }
    }
    for(i = 1; i <= m; i++){
        for(j = 1; j <= m; j++){
            if(i == j || !con[i][j])continue;
            printf("%d %d\n", i, j);
        }
    }
    return 0;
}
View Code

 

posted @ 2015-07-21 01:11  bbbbq  阅读(136)  评论(0编辑  收藏  举报