8月21号的练习:POJ 1511&&HDU 1018&&HDU 2571&&HDU 1533&&HDU 2554

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\n",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\n",(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\n",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\n");
14         else
15             printf("N\n");
16     }
17     return 0;
18 }

 

 

posted on 2013-08-22 12:55  ~~碾压机  阅读(222)  评论(0编辑  收藏  举报