放到图论里面,是因为用到了近似Floyd的算法。这题的输入麻烦,到最后直接用C++搞定了。 题目给出一系列物品之间的交换关系(比如6个i交换15个k),要求递推计算出给出的物品之间交换关系。采用的方法是建立图。a[i][k]代表了i和k交换时需要i的个数,a[k][i]是需要k的个数。每次更新信息之后对图遍历,对于那些已知a[i][j]和a[j][k]的路径,求出a[i][k],就如同Floyd求最短路径一样。 其实不用vector和string也可以解决,但是懒惰了 = = 。 PS:到了寒假,ZOJ似乎又复苏了,做题目的人好多。当初信心满满地想着要在3月份前做到400题,现在看起来像个笑话。好吧……随便做点,我最大的计划就是没有计划。 #include <iostream>#include <vector>#include <string>#include <cstring>using namespace std; int a[60][60];vector < string > sv; void ps (){ int i, k; for ( i = 0; i < sv.size (); i ++ ) { for ( k = 0; k < sv.size (); k ++ ) { printf ( "%d ", a[i][k] ); } }} int gcd ( int x, int y ){ int t; if ( x > y ) { t = x, x = y, y = t; } while ( x ) { t = x; x = y % x; y = t; } return y;} int index ( string str ) { int i; for ( i = 0; i < sv.size (); i ++ ) { if ( str == sv[i] ) { return i; } } sv.push_back ( str ); return i;} void floyd (){ int i, k, j; for ( i = 0; i < sv.size (); i ++ ) { for ( k = 0; k < sv.size (); k ++ ) { if ( i == k ) continue; for ( j = 0; j < sv.size (); j ++ ) { if ( j == k ) continue; if ( a[j][k] ) continue; if ( a[i][k] && a[j][i] ) { int ta = a[i][j] * a[k][i]; int tb = a[i][k] * a[j][i]; int tc = gcd ( ta, tb ); a[j][k] = tb / tc, a[k][j] = ta / tc; } } } }} void print ( int ia, int ib ){ if ( a[ia][ib] ) { cout << a[ia][ib] << " " << sv[ia] << " = " << a[ib][ia] << " " << sv[ib] << endl; } else { cout << "? " << sv[ia] << " = " << "? " << sv[ib] << endl; }} int main (){ //freopen ( "in.txt", "r", stdin ); char op; string sa, sb; int ia, ib, na, nb, nc; memset ( a, 0, sizeof ( a ) ); sv.clear (); while ( cin >> op ) { if ( op == '.' ) break; else if ( op == '!' ) { cin >> na >> sa >> op >> nb >> sb; ia = index ( sa ), ib = index ( sb ); nc = gcd ( na, nb ); a[ia][ib] = na / nc, a[ib][ia] = nb / nc; floyd (); } else { cin >> sa >> op >> sb; ia = index ( sa ), ib = index ( sb ); print ( ia, ib ); } } return 0;}

评论