Invitation Cards POJ 1511
较水的题,可以说是一道模板题了。。。
spfa+邻接表
但是有几个注意的地方:
1,题目给出的数据较大,只能用邻接表,并且要__int64的配合。
2,题目要求来回的最短路,需要建立两个邻接表(反向可以了)。
1 #include<iostream> 2 #include<algorithm> 3 #include<stdio.h> 4 #include<string.h> 5 #include<queue> 6 using namespace std; 7 const __int64 max1=1000000005; 8 int vis[1000005],pre[1000005],pre1[1000005],t,d1; 9 __int64 b[1000005];//需要用__int64 10 struct line 11 { 12 int left; 13 int right; 14 int num; 15 int Next; 16 }a[1000005],b1[1000005];//建立两个邻接表(其实建立一个再反向就行了) 17 void add(int left,int right,int num)//******* 18 { 19 a[t].left=left; 20 a[t].right=right; 21 a[t].num=num; 22 a[t].Next=pre[left]; 23 pre[left]=t++; 24 } 25 void add1(int left,int right,int num)//******* 26 { 27 b1[d1].left=left; 28 b1[d1].right=right; 29 b1[d1].num=num; 30 b1[d1].Next=pre1[left]; 31 pre1[left]=d1++; 32 } 33 int main() 34 { 35 int n,m,left,right,num,i,p,k,j,t1; 36 __int64 s;//需要用__int64 37 queue<int> Q; 38 scanf("%d",&t1); 39 while(t1--) 40 { 41 scanf("%d%d",&n,&m); 42 memset(pre,-1,sizeof(pre)); 43 memset(pre1,-1,sizeof(pre1)); 44 t=1;d1=1; 45 while(m--) 46 { 47 scanf("%d%d%d",&left,&right,&num); 48 if(left!=right) 49 { 50 add(left,right,num); 51 add1(right,left,num); 52 } 53 } 54 s=0; 55 memset(vis,0,sizeof(vis));//************* 56 for(i=1;i<=n;i++) 57 b[i]=max1; 58 b[1]=0; 59 Q.push(1); 60 while(!Q.empty()) 61 { 62 p=Q.front(); 63 Q.pop(); 64 vis[p]=0; 65 for(i=pre[p];i+1;i=a[i].Next) 66 { 67 k=a[i].right; 68 if(b[k]>a[i].num+b[p]) 69 { 70 b[k]=a[i].num+b[p]; 71 if(!vis[k]) 72 { 73 Q.push(k); 74 vis[k]=1; 75 } 76 } 77 } 78 } 79 for(i=2;i<=n;i++) 80 s+=b[i];//**************************两次spfa() 81 memset(vis,0,sizeof(vis));//****************两次spfa() 82 for(i=1;i<=n;i++) 83 b[i]=max1; 84 b[1]=0; 85 Q.push(1); 86 while(!Q.empty()) 87 { 88 p=Q.front(); 89 Q.pop(); 90 vis[p]=0; 91 for(i=pre1[p];i+1;i=b1[i].Next) 92 { 93 k=b1[i].right; 94 if(b[k]>b1[i].num+b[p]) 95 { 96 b[k]=b1[i].num+b[p]; 97 if(!vis[k]) 98 { 99 Q.push(k); 100 vis[k]=1; 101 } 102 } 103 } 104 } 105 for(i=2;i<=n;i++) 106 s+=b[i];//********************** 107 printf("%I64d ",s); 108 } 109 return 0; 110 }
Big Number HDU 1018
N!=1*2*3....*n
求位数我们一般用对一个数取对数就可以了 ,
log10(n!)=log10(1)+ log10(2) +log10(3)...+log10(n);
所以循环求和就可以了!
但是这里注意一点 结果要加1!因为这里计算出来的 log10(1)=0 !
所以结果要加上这个误差 ‘1’
1 #include<iostream> 2 #include<algorithm> 3 #include<stdio.h> 4 #include<math.h> 5 using namespace std; 6 int main() 7 { 8 int t,n,i; 9 scanf("%d",&t); 10 while(t--) 11 { 12 scanf("%d",&n); 13 double sum=0; 14 for(i=1;i<=n;i++) 15 sum+=log10(i+0.0); 16 printf("%d ",(int)sum+1); 17 } 18 return 0; 19 }
命运 HDU 2571
简单DP问题:
设 d[ i ][ j ] 表示走到坐标为(i, j)的格子时最大的幸运值。
状态转移方程:
d[ i ][ j ] = max { map [ i - 1][ j ], map [ i ] [ j - 1], map [ i ][ k ]} + map[ i ][ j ] ,j % k == 0
分三种情况,第一列 d[i][j] = d[i-1][j] + map[i][j] ;
第一行 d[ i ][ j ] = max { map [ i ] [ j - 1], map [ i ][ k ] } + map[ i ][ j ] ,j % k == 0
其他行列 d[ i ][ j ] = max { map [ i - 1][ j ], map [ i ] [ j - 1], map [ i ][ k ]} + map[ i ][ j ] ,j % k == 0
1 #include<iostream> 2 #include<stdio.h> 3 #include<algorithm> 4 using namespace std; 5 int a[25][1005]; 6 int main() 7 { 8 int t,n,m,i,j,k; 9 scanf("%d",&t); 10 while(t--) 11 { 12 scanf("%d%d",&n,&m); 13 for(i=1;i<=n;i++) 14 for(j=1;j<=m;j++) 15 scanf("%d",&a[i][j]); 16 for(i=1;i<=n;i++) 17 for(j=1;j<=m;j++) 18 { 19 if(i==1&&j==1) 20 continue; 21 int s=-105,s1=-105,s2=-105; 22 if(j-1>=1) 23 s=a[i][j]+a[i][j-1]; 24 if(i-1>=1) 25 s1=a[i][j]+a[i-1][j]; 26 s1=max(s1,s); 27 for(k=j-1;k>=1;k--) 28 if(j%k==0) 29 { 30 s2=a[i][j]+a[i][k]; 31 s1=max(s1,s2); 32 } 33 a[i][j]=s1; 34 } 35 printf("%d ",a[n][m]); 36 } 37 }
Going Home HDU 1533
一道二分图求最小权值得模板题:参见:http://www.cnblogs.com/tt123/p/3265533.html
N对数的排列问题 HDU 2554
数论题:具体参见:http://www.cnblogs.com/ACMan/archive/2012/12/03/2800271.html
1 #include<iostream> 2 #include<algorithm> 3 #include<stdio.h> 4 using namespace std; 5 int main() 6 { 7 int n; 8 while(scanf("%d",&n)!=EOF) 9 { 10 if(n==0) 11 break; 12 if(n%4==0||(n+1)%4==0) 13 printf("Y "); 14 else 15 printf("N "); 16 } 17 return 0; 18 }