|
2009年8月7日
這個題目我錯了很久,一直錯的原因是我沒有真正的理解題目的意思。 在 1 ABAB 這組數據上錯了,改過來之后就過了,下一次一定要好好讀題。 這一次是盡量用C++來寫,在用rfind函數的時候出了一點小問題,應該是從這個字符往前推一位開始查找,若是第一個字符,就不能調用函數了,不然就會出錯。所以就多加了一個判斷,影響了程序的可讀性。下一次要找到一個不需要這樣判斷的方法。
#include<iostream>
#include<string>
#define DEBUG 1
using namespace std ;

const int cap = 33 ;

char salon[cap] ;
string in ;

int check( int avai )
  {
int i, j, pos(-1), flag, away(0) ;
 for( i=0; i<in.size(); ++i ) {
if( i >= 1 )
pos = in.rfind( in[i], i ) ;
 if( pos >= 0 ) {
flag = 0 ;
 for( j=0; j<avai; ++j ) {
 if( salon[j] == in[i] ) {
salon[j] = '\0' ;
flag = 1 ;
break ;
}
}
 if( !flag ) {
 for( j=0; j<avai; ++j ) {
 if( !salon[j] ) {
flag = 1 ;
break ;
}
}
}
if( !flag )
++away ;
}
 else {
 for( j=0; j<avai; ++j ) {
 if( !salon[j] ) {
salon[j] = in[i] ;
break ;
}
}
}
}
return away ;
}

void output( int away )
  {
if( away )
cout << away << " customer(s) walked away." << endl ;
else
cout << "All customers tanned successfully." << endl ;
}

int main( )
  {
#if DEBUG
freopen("C:\\Documents and Settings\\Administrator\\桌面\\in.in","r",stdin) ;
freopen("C:\\Documents and Settings\\Administrator\\桌面\\out.out","w",stdout) ;
#endif

int avai, away ;
 while( cin >> avai ) {
if( avai == 0 )
break ;
cin >> in ;
away = check( avai ) ;
output( away ) ;
}
return 0 ;
}

2009年7月26日
好久都沒有寫解題總結了,手生了。抓緊時間做題,不然等到開學了,就不能這么爽的做題了。
這個題數據量不大,可以用回溯。剛開始做的時候,是用廣搜,但是寫起來超麻煩,代碼量極大,很容易出錯。參考了大牛們的做法,才想起來和N皇后問題很像。我們可以從一個點出發,然后往右下擴散,擴散完了之后,再回溯,再擴散…… 問題解決。
#include<iostream>
#define DEBUG 0
using namespace std ;

int n, maxi ;
char a[5][5] ;

bool legal( int x, int y )
  {
int i, j ;
 for( i=x-1; i>=0; --i ) {
if( a[i][y] == '@' )
return false ;
else if( a[i][y] == 'X' )
break ;
}
 for( j=y-1; j>=0; --j ) {
if( a[x][j] == '@' )
return false ;
else if( a[x][j] == 'X' )
break ;
}
return true ;
}

void trace( int x, int y, int geshu )
  {
if( x == n )
maxi = maxi>geshu ? maxi:geshu ;
 else {
if( y == n )
trace( x+1, 0, geshu ) ;
 else {
 if( a[x][y]=='.' && legal( x, y ) ) {
// 回溯標記
a[x][y] = '@' ;
trace( x, y+1, geshu+1 ) ;
a[x][y] = '.' ;
}
trace( x, y+1, geshu ) ;
}
}
}

int main()
  {
#if DEBUG
freopen("C:\\Documents and Settings\\Administrator\\桌面\\in.in","r",stdin) ;
freopen("C:\\Documents and Settings\\Administrator\\桌面\\out.out","w",stdout) ;
#endif

int i, j ;
 while( cin >> n ) {
if( !n )
break ;
 for( i=0; i<n; ++i ) {
 for( j=0; j<n; ++j ) {
cin >> a[i][j] ;
}
}
maxi = 0 ;
// 從0,0開始回溯
trace( 0, 0, 0 ) ;
cout << maxi << endl ;
}
return 0 ;
}

2009年6月5日
簡單而且經典的搜索題,用回溯做。對于什么是回溯什么是DFS我分不清。就是按位逐個判斷,直到找到結果,或者出界退出。
#include<iostream>
#include<cmath>
using namespace std ;
int n, a[111], k, ans[22], anscnt ;
 int p[42]= {0,0,2,3,0,5,0,7,0,0,0,11,0,13,0,0,0,17,0,19,0,
0,0,23,0,0,0,0,0,29,0,31,0,0,0,0,0,37,0,0,0,41} ;

int rev[100][20], revcnt ;

void DFS( int m, int geshu )
  {
int i, j ;
 if( geshu == n && p[1+m] ) {
cout << ans[0] ;
 for( i=1; i<n; ++i ) {
cout << " " << ans[i] ;
rev[revcnt][i] = ans[i] ;
}
++revcnt ;
cout << "\n" ;
}
else if( geshu == n )
return ;
 for( j=2; j<=n; ++j ) {
 if( j<p[j+m] && !a[j] ) {
a[j] = 1 ;
ans[geshu] = j ;
DFS( j, geshu+1 ) ;
a[j] = 0 ;
}
}
}

int main( )
  {
int i, j ;
 for( j=1; cin >> n; ++j ) {
cout << "Case "<< j << ":\n" ;
for( i=0; i<111; ++i )
a[i] = 0 ;
revcnt = 0 ;
k = 1 ;
ans[0] = 1 ;
anscnt = 1 ;
DFS( 1, 1 ) ;
cout << "\n";
}
return 0 ;
}

2009年5月30日
好幾天都沒有刷題了,心里好煩躁啊!
今天終于又做了一個不是很水的題目,數論的,大整數取余,直接暴力過了。其中又學了一種素數的篩選法,效率比我以前用的方法都要高。他不計算,只是篩選。這樣一來效率就高了很多。還有一個地方,就是大整數的取余,從高位,到低位,邊乘邊取余,根據的是同余定理。
#include <stdio.h>
#include <string.h>
#include <stdlib.h>

int p[1000000] ;
char pr[1000000] ;
int len, pnum, num[14] ;

void prime( )
  {
int i, j ;
// 篩選素數
 for( i=2; i<1000000; ++i ) {
pr[i] = 1 ;
}
 for( i=2,pnum=0; i<1000000; ++i ) {
 if( pr[i] ) {
p[pnum++] = i ;
for( j=i+i; j<1000000; j+=i )
pr[j] = 0 ;
}
}
}

int mod( int n )
  {
__int64 m=0 ;
int i ;
// 求余數
 for( i=len-1; i>=0; --i ) {
m = ( m*100000000+num[i] ) % n ;
}
return m ;
}

int main()
  {
char a[111] ;
int i, j, div, flag ;
prime( ) ;
 while( scanf("%s%d", a, &div ) && div && a[0]!='0' ) {
len = strlen( a ) ;
for( i=0; i<14; ++i )
num[i] = 0 ;
 for( i=0; i<len; ++i ) {
//逢一億進位
j = (len+7-i) / 8 - 1 ;
num[j] = num[j]*10 + a[i]-'0' ;
}
len = (len+7)/8 ;
flag = 1 ;
 for( i=0; p[i]<div && i<pnum; ++i ) {
 if( mod( p[i] ) == 0 ) {
flag = 0 ;
break ;
}
}
if( flag )
printf("GOOD\n") ;
else
printf("BAD %d\n", p[i] ) ;
}
system("pause");
return 0 ;
}

2009年5月22日
應該說是一個純數學的題目,考察錯排的概率。
#include <stdio.h>
#define DEBUG 1
int main()
  {
#if DEBUG
freopen("C:\\Documents and Settings\\Administrator\\桌面\\in.in","r",stdin) ;
freopen("C:\\Documents and Settings\\Administrator\\桌面\\out.out","w",stdout) ;
#endif
__int64 i, n, sets, s, fenmu ;
double p, temp ;
scanf("%I64d", &sets ) ;
 while( sets-- ) {
scanf("%I64d", &n ) ;
p = 1 ;
s = 1 ;
fenmu = 1 ;
 for( i=1; i<=n; ++i ) {
s *= -1 ;
fenmu *= i ;
p += s/(double)fenmu ;
}
printf("%.2lf%%\n", 100*p ) ;
}
}

2009年5月21日
這一題就是單純的考察錯排,也就是考察遞推。
基本形式:d[1]=0; d[2]=1 遞歸式:d[n]= (n-1)*( d[n-1] + d[n-2])
這就是著名的錯排公式
#include <stdio.h>
#define DEBUG 1
int main()
  {
#if DEBUG
freopen("C:\\Documents and Settings\\Administrator\\桌面\\in.in","r",stdin) ;
freopen("C:\\Documents and Settings\\Administrator\\桌面\\out.out","w",stdout) ;
#endif

__int64 i, n, s, geshu, a1, a2, temp ;
 while( EOF != scanf("%I64d", &n ) ) {
a1 = 0 ;
a2 = 1 ;
 for( i=1; i<=n; ++i ) {
temp = a2 ;
a2 = (i-1) * (a1+a2) ;
a1 = temp ;
}
printf("%I64d\n", a2 ) ;
}
return 0 ;
}

2009年5月12日
判定素數的,水題,主要是練習一下篩選法。
#include <stdio.h>
#include <math.h>
#define DEBUG 1
short a[1000000] ;
int main()
  {
#if DEBUG
freopen("C:\\Documents and Settings\\Administrator\\桌面\\in.txt","r",stdin);
freopen("C:\\Documents and Settings\\Administrator\\桌面\\out.txt","w",stdout);
#endif
int i, j, n, flag ;
double temp ;
 for( i=2; i<1000000; ++i ) {
if( a[i] )
continue ;
for( j=i; j<1000000; j+=i )
a[j] = 1 ;
temp = sqrt( i ) ;
flag = 1 ;
 for( j=2; j<=temp; ++j ) {
 if( i%j == 0 ) {
flag = 0 ;
break ;
}
}
if( flag )
a[i] = 0 ;
}
 while( scanf("%d", &n ) && n ) {
 for( i=3; i<n; i+=2 ) {
 if( !a[i] && !a[n-i] ) {
printf("%d = %d + %d\n", n, i, n-i ) ;
break ;
}
}
}
return 0 ;
}

2009年5月11日
摘要: 本來是一道水題,模擬的。但是我當時把一個int變量定義成char型的,結果是死活都調試不出來!一直WA 。最后還是自己檢查出來了。
1#include <stdio.h> 2#include <memory.h>... 閱讀全文
2009年5月10日
2009年5月8日
剛開始的時候我不知道這一題該如何來做,我當時想到了用搜索,但是數據量太大,可能會超時。隊友這一題說可以用最短路徑的方法來做。我實在是想不起來如何做,因為最短路徑的算法我只學了Dijsktra。我在網上搜了一下,發現別人用的全是Floyd算法。我就學習了一下Floyd。其精髓就是一個三重循環。以最外層變量為中樞點。不斷的求得兩個點之間的最短路徑。現在我只理解到了這里,有待于以后的提高! 對于這一題,只要能夠找到一個頂點,讓他的值比1大,就說明可以錢生錢。
#include <stdio.h>
#include <string.h>
#include <memory.h>
#define DEBUG 1
int n ;
char mo[31][30] ;
double map[31][31] ;

int Find( char *t )
  {
int i ;
for( i=1; i<=n; ++i )
if( !strcmp( mo[i], t ) )
return i ;
}

void Floyd( )
  {
int i, j, k ;
for( k=1; k<=n; ++k )
for( i=1; i<=n; ++i )
for( j=1; j<=n; ++j )
if( map[i][j] < map[i][k]*map[k][j] )
map[i][j] = map[i][k]*map[k][j] ;
}

void In( )
  {
int i, x, y, sets ;
char a[30], b[30] ;
double rate ;
for( i=1; i<=n; ++i )
scanf("%s", mo[i] ) ;
scanf("%d", &sets ) ;
 for( i=1; i<=sets; ++i ) {
scanf("%s %lf %s", a, &rate, b ) ;
x = Find( a ) ;
y = Find( b ) ;
map[x][y] = rate ;
}
}

void Judge( )
  {
int flag, i ;
flag = 0 ;
 for( i=1; i<=n; ++i ) {
 if( map[i][i] >= 1 ) {
flag = 1 ;
break ;
}
}
if( flag )
printf("Yes\n") ;
else
printf("No\n") ;
}

int main()
  {
#if DEBUG
freopen("C:\\Documents and Settings\\Administrator\\桌面\\in.in","r",stdin) ;
freopen("C:\\Documents and Settings\\Administrator\\桌面\\out.out","w",stdout) ;
#endif
int i ;
 for( i=1; scanf("%d", &n) && n; ++i ) {
printf("Case %d: ", i ) ;
memset( map, 0, sizeof(map) ) ;
In( ) ;
Floyd( ) ;
Judge( ) ;
}
return 0 ;
}
|