往年的\(noip\)原題,純搜索吧,沒啥可講的,直接暴力枚舉,暴力判斷就行c++
沒有必要每次都存一個很大的字符串,只要存當前的字符串就好了算法
每一個字符串能夠用兩次數組
不能包含關係。。。好像也沒啥了吧優化
#include <bits/stdc++.h> using namespace std; const int N = 23; int n , ans = -1 , v[N] ; string str[N]; inline int check( string s1 , string s2) { register bool flag; for( register int i = 1 ; i < min( s1.size() , s2.size() ) ; i ++ ) { flag = 1; for( register int j = 0 ; j < i && flag ; j ++ ) { if( s1[s1.size() - i + j ] != s2[j] ) flag = 0; } if( flag ) return i; } return 0; } inline void dfs( string cur , int x ) { ans = max( ans , x ); for( register int i = 1 , k ; i <= n ; i ++ ) { if( v[i] >= 2 ) continue; k = check( cur , str[i] ); if( k ) { v[i] ++; dfs( str[i] , x + str[i].size() - k ); v[i] --; } } return ; } int main() { cin >> n; for( register int i = 1 ; i <= n + 1 ; i ++ ) cin >> str[i]; dfs( ' ' + str[ n + 1 ] , 1 ); cout << ans << endl; return 0; }
這也是一個經典的揹包問題,揹包求最小費用spa
f[i][j]
表示前\(i\)個物品用了\(j\)的體力所能填滿的最大空間,顯然滾動數組優化一維空間code
而後枚舉一下體力,找到最早填滿所有體積的一個便可ip
簡單分析一下,當花費的體力增長時,所填滿的體積保證不會減少,知足單調性ci
二分查找會更快字符串
#include<bits/stdc++.h> using namespace std; const int N = 10005; int n , V , power ,f[N] , use; bool flag = 0; inline int read() { register int x = 0; register char ch = getchar(); while( ch < '0' || ch > '9' ) ch = getchar(); while( ch >= '0' && ch <= '9' ) { x = ( x << 3 ) + ( x << 1 ) + ch - '0'; ch = getchar(); } return x; } int main() { V = read() , n = read() , power = read(); for( register int i = 1 , v , w ; i <= n ; i ++ ) { v = read() , w = read(); for( register int j = power ; j >= w ; j -- ) f[j] = max( f[j] , f[ j - w ] + v ); } use = lower_bound( f + 1 , f + 1 + power , V ) - f; if( f[use] >= V ) printf( "%d\n" , power - use ); else puts("Impossible"); return 0; }
相似P1510
精衛填海,不過這是徹底揹包稍做修該便可get
不過要注意f[need]
並不是最優解,由於能夠多買點,只要比須要的多便可
#include <bits/stdc++.h> using namespace std; const int N = 505005 , INF = 0x7f7f7f7f; int n , need , f[N] , ans = INF ; inline int read() { register int x = 0; register char ch = getchar(); while( ch < '0' || ch > '9' ) ch = getchar(); while( ch >= '0' && ch <= '9' ) { x = ( x << 3 ) + ( x << 1 ) + ch - '0'; ch = getchar(); } return x; } int main() { n = read() , need = read(); memset( f , INF , sizeof(f) ) , f[0] = 0; for( register int i = 1 , w , v ; i <= n ; i ++ ) { v = read() , w = read(); for( register int j = v ; j <= need + 5000; j ++ ) f[j] = min( f[j] , f[ j - v ] + w ) ; } for( register int i = need ; i <= need + 5000 ; i ++ ) ans = min( ans , f[i] ); cout << ans << endl; return 0; }
\(noip\)的原題,由於Luogu跑的比較快,因此能夠用非正確算法過這道題
對於讀入進來的數咱們能夠取一個模,爲何呢由於一個數等於0
那麼這個數模一個數也等於0
可是模一個數等於0
的數可不必定等於0
,爲了儘量的避免這種狀況,要儘量的採用一個大質數,質數越大,越不容易出現問題
而後在用秦九韶算法能夠\(O(n)\)的算出結果,因此枚舉每個數\(O(n)\)的判斷便可,因此總複雜度\(O(nm)\)
#include <bits/stdc++.h> #define LL long long using namespace std; const int N = 105 , M = 1e6 + 5 , p = 1e9+7; int n , m , tot , ans[M]; LL a[N]; inline void read( LL & a ) { register LL f = 1; register char ch = getchar(); for( ; ch < '0' || ch > '9' ; ( ch == '-' ? f = - 1 : f ) , ch = getchar() ); for( ; ch >= '0' && ch <= '9' ; a = ( ( a << 3 ) % p + ( a << 1 ) % p + ch - '0' ) % p , ch = getchar() ); a *= f ; return ; } inline bool check( LL x ) { register LL s = a[n]; for( register int i = n - 1 ; i >= 0 ; i -- ) s = ( s * x + (LL)a[i] ) % p ; return !s; } int main() { cin >> n >> m; for( register int i = 0 ; i <= n ; read( a[i] ) , i ++ ); for( register int i = 1 ; i <= m ; i ++ ) { if( check( i ) ) ans[ ++ tot ] = i; } printf( "%d\n" , tot ); for( register int i = 1 ; i <= tot ; printf( "%d\n" , ans[i] ) , i ++ ); return 0; }
\(Noip\)原題,首先考慮如何知足第一個條件,反向建圖,充目標點開始作\(DFS\),把全部到達的點打上標記,這樣若是一個點的子節點所有都被打上標記,那麼這個點就知足第一條件
第二個條件就是裸的最短路,直接在被標記的點的中跑一遍最短路
#include <bits/stdc++.h> #define PII pair< int, int > #define F first #define S second using namespace std; const int N = 10005 , INF = 0x7f7f7f7f; int n , m , st , ed , dis[N]; bool vis[N] , can[N]; set< PII > s; vector<int> e[N] , t[N] ; inline int read() { register int x = 0; register char ch = getchar(); while( ch < '0' || ch > '9' ) ch = getchar(); while( ch >= '0' && ch <= '9' ) { x = ( x << 3 ) + ( x << 1 ) + ch - '0'; ch = getchar(); } return x; } inline void add( int x , int y ) { e[x].push_back(y) , t[y].push_back(x); } inline void dfs( int x ) { can[x] = 1; for( register auto v : t[x] ) { if( can[v] ) continue; dfs( v ); } return ; } inline bool panding( int x ) { for( register auto v : e[x] ) { if( can[v] ) continue; return 1; } return 0; } inline void Dijkstra() { for( register int i = 1 ; i <= n ; i ++ ) dis[i] = INF; s.insert( { 0 , st } ) , dis[st] = 0; for( register int u , w; s.size() ; ) { u = s.begin() -> S , s.erase( s.begin() ); if( vis[u] ) continue; vis[u] = 1; if( panding(u) ) continue; if( u == ed ) return ; for( register auto v : e[u] ) { if( dis[v] <= dis[u] + 1 ) continue; dis[v] = dis[u] + 1; s.insert( { dis[v] , v } ); } } } int main() { n = read() , m = read(); for( register int x , y ; m >= 1 ; x = read() , y = read() , add( x , y ) , m -- ); st = read() , ed = read(); dfs(ed); Dijkstra(); cout << ( dis[ed] == INF ? -1 : dis[ed] ) << endl; return 0; }