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; }
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 }
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; }
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; }
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; }
时间: 2024-10-09 17:12:17