2013年7月20号: Flip Game&&The Pilots Brothers' refrigerator&&Coin Change&&Discrete Function&&Football Gambling II
Flip Game
http://acm.tzc.edu.cn/acmhome/problemdetail.do?method=showdetail&id=3248
实实在在的深搜问题,注意几点:关于这类问题,最好变成0和1来回的切换(简洁,清晰)
思路的话,因为深搜这是第一题,也是最难懂的,所以多看看,多想想。
1 #include<iostream> 2 #include<stdio.h> 3 #include<algorithm> 4 using namespace std; 5 int a[4][4]; 6 int flag=0,step; 7 int range()//与最终状态进行判断(全为黑或全为白) 8 { 9 int i,j; 10 for(i=0;i<4;i++) 11 for(j=0;j<4;j++) 12 { 13 if(a[i][j]!=a[0][0]) 14 return 0; 15 } 16 return 1; 17 } 18 void turn(int i,int j)//转换 19 { 20 a[i][j]=!a[i][j]; 21 if(i>0) 22 a[i-1][j]=!a[i-1][j]; 23 if(i<3) 24 a[i+1][j]=!a[i+1][j]; 25 if(j>0) 26 a[i][j-1]=!a[i][j-1]; 27 if(j<3) 28 a[i][j+1]=!a[i][j+1]; 29 } 30 int dfs(int i,int j,int k)//深搜 31 { 32 if(k==step) 33 { 34 flag=range(); 35 return 0; 36 } 37 if(flag||i==4) return 1; 38 turn(i,j); 39 if(j<3) 40 dfs(i,j+1,k+1); 41 else 42 dfs(i+1,0,k+1); 43 turn(i,j); 44 if(j<3) 45 dfs(i,j+1,k); 46 else 47 dfs(i+1,0,k); 48 return 0; 49 } 50 int main() 51 { 52 char t; 53 int i,j; 54 for(i=0;i<4;i++) 55 {for(j=0;j<4;j++) 56 {scanf("%c",&t); 57 if(t=='b') 58 a[i][j]=1; 59 else 60 a[i][j]=0; 61 } 62 getchar(); 63 } 64 for(step=0;step<=16;step++) 65 { 66 flag=0; 67 dfs(0,0,0); 68 if(flag) break; 69 } 70 if(flag) 71 printf("%d\n",step); 72 else 73 printf("Impossible\n"); 74 return 0; 75 }
貌似还有个一样的:The Pilots Brothers' refrigerator http://poj.org/problem?id=2965
做法一模一样,就是要求具体的步骤:
1 #include<iostream> 2 #include<stdio.h> 3 #include<algorithm> 4 using namespace std; 5 int a[4][4],x[16],y[16]; 6 int flag=0,step; 7 int range() 8 { 9 int i,j; 10 for(i=0;i<4;i++) 11 for(j=0;j<4;j++) 12 { 13 if(a[i][j]!=1) 14 return 0; 15 } 16 return 1; 17 } 18 void turn(int i,int j) 19 { 20 int n; 21 for(n=0;n<4;n++) 22 a[i][n]=!a[i][n]; 23 for(n=0;n<4;n++) 24 a[n][j]=!a[n][j]; 25 a[i][j]=!a[i][j]; 26 } 27 int dfs(int i,int j,int k) 28 { 29 if(k==step) 30 { 31 flag=range(); 32 return 0; 33 } 34 if(flag||i==4) return 1; 35 turn(i,j); 36 if(j<3) 37 {x[k]=i; 38 y[k]=j; 39 dfs(i,j+1,k+1);} 40 else 41 { x[k]=i; 42 y[k]=j; 43 dfs(i+1,0,k+1);} 44 turn(i,j); 45 if(j<3) 46 dfs(i,j+1,k); 47 else 48 dfs(i+1,0,k); 49 return 0; 50 } 51 int main() 52 { 53 char t; 54 int i,j; 55 for(i=0;i<4;i++) 56 {for(j=0;j<4;j++) 57 {scanf("%c",&t); 58 if(t=='-') 59 a[i][j]=1; 60 else 61 a[i][j]=0; 62 } 63 getchar(); 64 } 65 for(step=0;step<=16;step++) 66 { 67 flag=0; 68 dfs(0,0,0); 69 if(flag) break; 70 } 71 if(flag) 72 {printf("%d\n",step); 73 for(i=0;i<step;i++) 74 printf("%d %d\n",x[i]+1,y[i]+1); 75 } 76 return 0; 77 }
Coin Changehttp://acmpj.zstu.edu.cn/JudgeOnline/showproblem?problem_id=2613
暴力求解:
看懂题目,不多说
1 #include <stdio.h> 2 #include <string.h> 3 #include <algorithm> 4 #include<iostream> 5 using namespace std; 6 int main() 7 { 8 int a,b,c,d,e,num,n; 9 while(scanf("%d",&n)!=EOF) 10 { 11 num=0; 12 for(a=0;a<=n;a++) 13 for(b=0;b*5<=n-a;b++) 14 for(c=0;c*10<=n-a-5*b;c++) 15 for(d=0;d*25<=n-a-5*b-10*c;d++) 16 {e=n-a-5*b-10*c-25*d; 17 if(e%50==0&&a+b+c+d+e/50<=100) 18 num++;} 19 printf("%d\n",num); 20 } 21 return 0; 22 23 }
Discrete Functionhttp://acm.timus.ru/problem.aspx?num=1010
这题实际上是很简单的,只要意识到所求倾角最大的连线的两个端点必定是相邻的点就容易了。
两点连线的倾角的正切值(tan)等于这两点的纵坐标之差除以横坐标之差。由于这两点是相邻的点,所以横坐标之差为 1,也就是说,直接等于纵坐标之差。
题目中说的:“Each value of the function is longint (signed long in C++).”,即:该离散函数的值域是 C++ 中的 signed long 数据类型,实际上相当于 C# 中的 int ( 即: System.Int32 ) 数据类型,取值范围是 -2,147,483,648 到 +2,147,483,647。所以可以用 int.Parse() 方法来读取输入。但是进行计算时必须使用 C# 的 long ( 即: System.Int64 ) 数据类型,相当于 C++ 中的 signed long long 数据类型,取值范围是 -9,223,372,036,854,775,808 到 +9,223,372,036,854,775,807,不然计算时就有可能溢出。//貌似这种问题最头痛,而关于什么什么的取值范围不太清楚!注意注意
1 #include<iostream> 2 #include<stdio.h> 3 #include<algorithm> 4 #include<math.h> 5 #include<cmath> 6 using namespace std; 7 int main() 8 { 9 __int64 a[100005],Max;//要用64位保证不会溢出!!int的前面有俩杠!! 10 int t,i,d; 11 scanf("%d",&t); 12 for(i=0;i<t;i++) 13 scanf("%I64d",&a[i]); 14 Max=0; 15 for(i=0;i<t-1;i++) 16 { 17 if(abs(a[i]-a[i+1])>Max) 18 { 19 d=i; 20 Max=abs(a[i]-a[i+1]); 21 } 22 } 23 printf("%d %d\n",d+1,d+2); 24 return 0; 25 }
Football Gambling IIhttp://acm.zju.edu.cn/onlinejudge/showProblem.do?problemCode=3356
题意:
每组测试数据 S 表示初始硬币个数,a,b,c分别表示题中所述赔率
赌博有三种结果,只可能猜中一种情况,猜中的 才可获利。
如果投 a,num个硬币【硬币不可拆分】并且结果是 a 那么可获利 floor(a*num)【即去掉小数部分】
对于 S 个硬币你可随意选择投或不投,或者投给哪一个
最后输出最糟的情况的获利【肯定是 >= S的】//赔率不是什么成功率或失败率!
总的来说,就是从1枚举到 S,每次选一个盈利最小的,然后硬币就投入进去,同时更新盈利,这样就保证了无论结果是a,b,c哪一种,都能至少不输钱。
you should caluate the maximum number of coins asmn will have after the gambling in the worst situation.//说明是要找投最多数量的硬币而盈利最小的获利。(这里更侧重的是要达到最多数量,而那时只要盈利就行了)
扩大一百倍
1 #include<stdio.h> 2 #include<string.h> 3 #include<iostream> 4 using namespace std; 5 6 int main() 7 { 8 int T; 9 int s,a,aa,b,bb,c,cc; 10 int ans; 11 int num[5]; 12 13 scanf("%d", &T); 14 while(T--) 15 { 16 scanf("%d%d.%d%d.%d%d.%d", &s,&a,&aa,&b,&bb,&c,&cc); //注意放大了100倍 17 memset(num, 0, sizeof(num)); 18 19 a = a*100+aa; 20 b = b*100+bb; 21 c = c*100+cc; 22 23 ans = s*100; 24 int sa,sb,sc; 25 for(int i = 1; i <= s; i++) 26 { 27 sa = a*num[1]; 28 sb = b*num[2]; 29 sc = c*num[3]; 30 31 if(sa <= sb && sa <= sc) 32 { 33 num[1]++; 34 } 35 else if(sb <= sa && sb <= sc) 36 { 37 num[2]++; 38 } 39 else if(sc <= sa && sc <= sb) 40 { 41 num[3]++; 42 } 43 44 sa = a*num[1]; 45 sb = b*num[2]; 46 sc = c*num[3]; 47 48 if(sa <= sb && sa <= sc) 49 { 50 ans = max(ans, sa+(s-i)*100); 51 } 52 else if(sb <= sa && sb <= sc) 53 { 54 ans = max(ans, sb+(s-i)*100); 55 } 56 else if(sc <= sa && sc <= sb) 57 { 58 ans = max(ans, sc+(s-i)*100); 59 } 60 61 } 62 printf("%d\n", ans/100); 63 } 64 return 0; 65 }