题意:
给你N个字符串,让你重新编写字典序,使得这N个字符串按照字典序排列
解题思路:
相邻的两个字符串直接相互比较,可以得出某些字母一定要在某些字母前面,让人联想到拓扑排序
因此建图,进行拓扑排序
注意:当前面全部相同的时候,长度大的排在后面是不行的,需要特判,这里wa了几次
// whn6325689 // Mr.Phoebe // http://blog.csdn.net/u013007900 #include <algorithm> #include <iostream> #include <iomanip> #include <cstring> #include <climits> #include <complex> #include <fstream> #include <cassert> #include <cstdio> #include <bitset> #include <vector> #include <deque> #include <queue> #include <stack> #include <ctime> #include <set> #include <map> #include <cmath> #include <functional> #include <numeric> #pragma comment(linker, "/STACK:1024000000,1024000000") using namespace std; typedef long long ll; typedef long double ld; typedef pair<ll, ll> pll; typedef complex<ld> point; typedef pair<int, int> pii; typedef pair<pii, int> piii; typedef vector<int> vi; #define CLR(x,y) memset(x,y,sizeof(x)) #define mp(x,y) make_pair(x,y) #define pb(x) push_back(x) #define lowbit(x) (x&(-x)) #define MID(x,y) (x+((y-x)>>1)) #define eps 1e-9 #define PI acos(-1.0) #define INF 0x3f3f3f3f #define LLINF 1LL<<62 template<class T> inline bool read(T &n) { T x = 0, tmp = 1; char c = getchar(); while((c < '0' || c > '9') && c != '-' && c != EOF) c = getchar(); if(c == EOF) return false; if(c == '-') c = getchar(), tmp = -1; while(c >= '0' && c <= '9') x *= 10, x += (c - '0'),c = getchar(); n = x*tmp; return true; } template <class T> inline void write(T n) { if(n < 0) { putchar('-'); n = -n; } int len = 0,data[20]; while(n) { data[len++] = n%10; n /= 10; } if(!len) data[len++] = 0; while(len--) putchar(data[len]+48); } //----------------------------------- int n; char s[147][147]; int G[147][147]; int in[147];//入度 char ans[147]; void toposort()//拓扑排序 { queue<int> q; int k=0; for(int i=0; i<26; i++) if(!in[i]) { q.push(i); ans[k++]='a'+i; } while(!q.empty()) { int f = q.front();q.pop(); for(int i=0; i<26; i++) { if(G[f][i]) { in[i]--; if(!in[i]) { q.push(i); ans[k++]='a'+i; } } } } if(k<26) { puts("Impossible"); } else { ans[k] = '\0'; puts(ans); } } int main() { while(read(n)) { CLR(in,0); CLR(G,0); for(int i=0; i<n; i++) scanf("%s",s[i]); int mark = 1; for(int i=0; i<n-1 && mark; i++) { int len1=strlen(s[i]); int len2=strlen(s[i+1]); int flag=0; for(int j=0; j<len1 && j<len2; j++) { if(s[i][j]!=s[i+1][j]) { if(!G[s[i][j]-'a'][s[i+1][j]-'a']) { G[s[i][j]-'a'][s[i+1][j]-'a']=1; in[s[i+1][j]-'a']++; } flag=1; break; } } if(!flag && len1>len2)//特判,前缀相同,且前一字符串币后一字符串还长,肯定不合法,这里wa了一次 mark=0; } if(!mark) { printf("Impossible\n"); return 0; } toposort(); } return 0; }
题意:
给你一些卡片,他们能够跳跃距离为L[i],花费为C[i]
求能够访问所有的点的最小花费是多少
解题思路:
就是通过将几个L[i]加加减减然后能够凑出 1 就能够访问所有的点
由裴蜀定理a*x + b*y = gcd(x,y) 可以得知,当x,y的最大公约数为1的时候,总存在a,b使得x,y凑出来为1,则满足题意
// whn6325689 // Mr.Phoebe // http://blog.csdn.net/u013007900 #include <algorithm> #include <iostream> #include <iomanip> #include <cstring> #include <climits> #include <complex> #include <fstream> #include <cassert> #include <cstdio> #include <bitset> #include <vector> #include <deque> #include <queue> #include <stack> #include <ctime> #include <set> #include <map> #include <cmath> #include <functional> #include <numeric> #pragma comment(linker, "/STACK:1024000000,1024000000") using namespace std; typedef long long ll; typedef long double ld; typedef pair<ll, ll> pll; typedef complex<ld> point; typedef pair<int, int> pii; typedef pair<pii, int> piii; typedef vector<int> vi; #define CLR(x,y) memset(x,y,sizeof(x)) #define mp(x,y) make_pair(x,y) #define pb(x) push_back(x) #define lowbit(x) (x&(-x)) #define MID(x,y) (x+((y-x)>>1)) #define eps 1e-9 #define PI acos(-1.0) #define INF 0x3f3f3f3f #define IINF 1<<30 #define LLINF 1LL<<62 template<class T> inline bool read(T &n) { T x = 0, tmp = 1; char c = getchar(); while((c < '0' || c > '9') && c != '-' && c != EOF) c = getchar(); if(c == EOF) return false; if(c == '-') c = getchar(), tmp = -1; while(c >= '0' && c <= '9') x *= 10, x += (c - '0'),c = getchar(); n = x*tmp; return true; } template <class T> inline void write(T n) { if(n < 0) { putchar('-'); n = -n; } int len = 0,data[20]; while(n) { data[len++] = n%10; n /= 10; } if(!len) data[len++] = 0; while(len--) putchar(data[len]+48); } //----------------------------------- int n, l[305], c[305]; map<int,int> dp[305]; int solve(int id=0, int gcd=0) { if(id>=n) return gcd==1?0:IINF; if(dp[id].count(gcd)) return dp[id][gcd]; return dp[id][gcd]=min(solve(id+1, __gcd(gcd, l[id]))+c[id],solve(id+1, gcd)); } int main() { read(n); for(int i=0; i<n; i++) read(l[i]); for(int i=0; i<n; i++) read(c[i]); int ans=solve(); if(ans >= IINF) write(-1); else write(ans); putchar('\n'); return 0; }