T1 洛谷 P2966 [USACO09DEC]牛收费路径Cow Toll Paths
题目描述
Like everyone else, FJ is always thinking up ways to increase his revenue. To this end, he has set up a series of tolls that the cows will pay when they traverse the cowpaths throughout the farm.
The cows move from any of the N (1 <= N <= 250) pastures conveniently numbered 1..N to any other pasture over a set of M (1 <= M <= 10,000) bidirectional cowpaths that connect pairs of different pastures A_j and B_j (1 <= A_j <= N; 1 <= B_j <= N). FJ has assigned a toll L_j (1 <= L_j <= 100,000) to the path connecting pastures A_j and B_j.
While there may be multiple cowpaths connecting the same pair of pastures, a cowpath will never connect a pasture to itself. Best of all, a cow can always move from any one pasture to any other pasture by following some sequence of cowpaths.
In an act that can only be described as greedy, FJ has also assigned a toll C_i (1 <= C_i <= 100,000) to every pasture. The cost of moving from one pasture to some different pasture is the sum of the tolls for each of the cowpaths that were traversed plus a *single additional toll* that is the maximum of all the pasture tolls encountered along the way, including the initial and destination pastures.
The patient cows wish to investigate their options. They want you to write a program that accepts K (1 <= K <= 10,000) queries and outputs the minimum cost of trip specified by each query. Query i is a pair of numbers s_i and t_i (1 <= s_i <= N; 1 <= t_i <= N; s_i != t_i) specifying a starting and ending pasture.
Consider this example diagram with five pastures:
The ‘edge toll‘ for the path from pasture 1 to pasture 2 is 3. Pasture 2‘s ‘node toll‘ is 5.
To travel from pasture 1 to pasture 4, traverse pastures 1 to 3 to 5 to 4. This incurs an edge toll of 2+1+1=4 and a node toll of 4 (since pasture 5‘s toll is greatest), for a total cost of 4+4=8.
The best way to travel from pasture 2 to pasture 3 is to traverse pastures 2 to 5 to 3. This incurs an edge toll of 3+1=4 and a node toll of 5, for a total cost of 4+5=9.
跟所有人一样,农夫约翰以着宁教我负天下牛,休叫天下牛负我的伟大精神,日日夜夜苦思生 财之道。为了发财,他设置了一系列的规章制度,使得任何一只奶牛在农场中的道路行走,都 要向农夫约翰上交过路费。 农场中由N(1 <= N <= 250)片草地(标号为1到N),并且有M(1 <= M <= 10000)条 双向道路连接草地A_j和B_j(1 <= A_j <= N; 1 <= B_j <= N)。
奶牛们从任意一片草 地出发可以抵达任意一片的草地。FJ已经在连接A_j和B_j的双向道路上设置一个过路费L_j (1 <= L_j <= 100,000)。 可能有多条道路连接相同的两片草地,但是不存在一条道路连接一片草地和这片草地本身。最 值得庆幸的是,奶牛从任意一篇草地出发,经过一系列的路径,总是可以抵达其它的任意一片 草地。 除了贪得无厌,叫兽都不知道该说什么好。
FJ竟然在每片草地上面也设置了一个过路费C_i (1 <= C_i <= 100000)。从一片草地到另外一片草地的费用,是经过的所有道路的过路 费之和,加上经过的所有的草地(包括起点和终点)的过路费的最大值。 任劳任怨的牛们希望去调查一下她们应该选择那一条路径。
她们要你写一个程序,接受K(1 <= K <= 10,000)个问题并且输出每个询问对应的最小花费。第i个问题包含两个数字s_i 和t_i(1 <= s_i <= N; 1 <= t_i <= N; s_i != t_i),表示起点和终点的草地。
输入输出格式
输入格式:
- Line 1: Three space separated integers: N, M, and K
- Lines 2..N+1: Line i+1 contains a single integer: C_i
- Lines N+2..N+M+1: Line j+N+1 contains three space separated
integers: A_j, B_j, and L_j
- Lines N+M+2..N+M+K+1: Line i+N+M+1 specifies query i using two space-separated integers: s_i and t_i
输出格式:
- Lines 1..K: Line i contains a single integer which is the lowest cost of any route from s_i to t_i
输入输出样例
输入样例#1:
5 7 2 2 5 3 3 4 1 2 3 1 3 2 2 5 3 5 3 1 5 4 1 2 4 3 3 4 4 1 4 2 3
输出样例#1:
8 9 n的范围支持n^3的Floyd,然后、、
1 #include <cstdio> 2 3 const int INF(0x3f3f3f3f); 4 const int N(250+26); 5 int n,m,p,point[N]; 6 int ans[N][N],maxp[N][N],dis[N][N]; 7 8 inline void read(int &x) 9 { 10 x=0; register char ch=getchar(); 11 for(; ch>‘9‘||ch<‘0‘; ) ch=getchar(); 12 for(; ch>=‘0‘&&ch<=‘9‘; ch=getchar()) x=x*10+ch-‘0‘; 13 } 14 15 #define min(a,b) (a<b?a:b) 16 #define max(a,b) (a>b?a:b) 17 18 int AC() 19 { 20 freopen("fee.in","r",stdin); 21 freopen("fee.out","w",stdout); 22 23 read(n),read(m),read(p); 24 for(int i=1; i<=n; ++i) 25 for(int j=1; j<=n; ++j) 26 dis[i][j]=INF*(i!=j); 27 for(int i=1; i<=n ;++i) 28 read(point[i]); 29 for(int u,v,w; m--; ) 30 { 31 read(u),read(v),read(w); 32 dis[u][v]=min(dis[u][v],w); 33 dis[v][u]=dis[u][v]; 34 } 35 for(int k=1; k<=n; ++k) 36 for(int i=1; i<=n; ++i) 37 for(int j=1; j<=n; ++j) 38 if(dis[i][j]>dis[i][k]+dis[k][j]) 39 { 40 dis[i][j]=dis[i][k]+dis[k][j]; 41 maxp[i][j]=max(point[i],point[j]); 42 maxp[i][j]=max(maxp[i][k],maxp[k][j]); 43 maxp[i][j]=max(maxp[i][j],point[k]); 44 } 45 else if(dis[i][j]<dis[i][k]+dis[k][j]) 46 maxp[i][j]=max(point[i],point[j]); 47 for(int s,t; p--; ) 48 { 49 read(s),read(t); 50 if(s==t) printf("%d\n",point[s]); 51 else if(dis[s][t]+maxp[s][t]>=INF) puts("-1"); 52 else printf("%d\n",dis[s][t]+maxp[s][t]); 53 } 54 return 0; 55 } 56 57 int Hope=AC(); 58 int main(){;}
20分。
先给点权排序,使的在最短路更新时,i-->j 这条路径上,依次枚举点权从小到大的中转点k
每次由最短路更新出ans,保证ans的正确、
1 #include <algorithm> 2 #include <cstdio> 3 4 const int INF(0x3f3f3f3f); 5 const int N(250+26); 6 int n,m,p,point[N],s[N]; 7 int ans[N][N],dis[N][N]; 8 9 inline void read(int &x) 10 { 11 x=0; register char ch=getchar(); 12 for(; ch>‘9‘||ch<‘0‘; ) ch=getchar(); 13 for(; ch>=‘0‘&&ch<=‘9‘; ch=getchar()) x=x*10+ch-‘0‘; 14 } 15 16 #define min(a,b) (a<b?a:b) 17 #define max(a,b) (a>b?a:b) 18 19 bool cmp(int a,int b) 20 { 21 return point[a]<point[b]; 22 } 23 24 int AC() 25 { 26 // freopen("fee.in","r",stdin); 27 // freopen("fee.out","w",stdout); 28 29 read(n),read(m),read(p); 30 for(int i=1; i<=n; ++i) 31 for(int j=1; j<=n; ++j) 32 ans[i][j]=dis[i][j]=INF*(i!=j); 33 for(int i=1; i<=n ;++i) 34 read(point[i]),s[i]=i,ans[i][i]=point[i]; 35 std::sort(s+1,s+n+1,cmp); 36 for(int u,v,w; m--; ) 37 { 38 read(u),read(v),read(w); 39 dis[u][v]=min(dis[u][v],w); 40 dis[v][u]=dis[u][v]; 41 } 42 for(int k=1; k<=n; ++k) 43 for(int i=1; i<=n; ++i) 44 for(int j=1; j<=n; ++j) 45 { 46 dis[s[i]][s[j]]=min(dis[s[i]][s[j]],dis[s[i]][s[k]]+dis[s[k]][s[j]]); 47 ans[s[i]][s[j]]=min(ans[s[i]][s[j]],dis[s[i]][s[j]]+ 48 max(point[s[k]],max(point[s[i]],point[s[j]]))); 49 } 50 for(int s,t; p--; ) 51 { 52 read(s),read(t); 53 if(ans[s][t]>=INF) puts("-1"); 54 else printf("%d\n",ans[s][t]); 55 } 56 return 0; 57 } 58 59 int Hope=AC(); 60 int main(){;}
AC
T2 走楼梯升级版
Description
在你成功地解决了上一道走楼梯后,xxy 不禁有些气恼,于是她又在楼梯上跳来跳去,想要你求出她跳的方案数。..
xxy 站在一个 tot 阶楼梯下面,他每次可以往上跳1—n步,往下跳1——m步(由于地心引力跳得比较远),而且在往下跳的时候只能踩在往上跳时踩过的格子。
现在 xxy 在楼梯上乱跳,想问她跳到楼梯顶上最后又跳回楼梯下面的方案数 mod 233333333。
注意:xxy 只能一直向上跳,跳到楼梯最上面,然后再往下跳,跳回楼梯最底下。
Input
一行3个整数 tot,n,m
Output
方案数 % 233333333
Example
Input
2
5 2 4
5 2 3
Output
52
42
Hint
10%的数据,1<=tot,n<=5,m=1
另外10%的数据, 1<=tot,n,m<=5
另外20%的数据, 1<=tot<=10000,1<=n,m<=5
另外20%的数据, 1<=tot<=10000,1<=n,m<=10
另外20%的数据, 1<=tot<=400000,1<=n,m<=5
对于100%的数据,1<=tot<=400000,1<=n,m<=10
考试想出正解做法,结果、、、没考虑long long ,还在预处理的时候打错变量了。。w(?Д?)w zz啊。
1 #include <cstring> 2 #include <cstdio> 3 4 const int mod(233333333); 5 const int N(400000+626); 6 int n,m,tot,a[N],f[N]; 7 8 inline void read(int &x) 9 { 10 x=0; register char ch=getchar(); 11 for(;ch>‘9‘||ch<‘0‘;) ch=getchar(); 12 for(;ch>=‘0‘&&ch<=‘9‘;ch=getchar()) x=x*10+ch-‘0‘; 13 } 14 15 int ret; 16 bool vis[N],vis_[N]; 17 void DFS_(int now) 18 { 19 if(now==0) 20 { 21 ret++; 22 ret%=mod; 23 return ; 24 } 25 for(int i=1; i<=m; ++i) 26 { 27 if(vis_[now-i]||(now-i<0)) continue; 28 if(!vis[now-i]) continue; 29 vis_[now-i]=1; 30 DFS_(now-i); 31 vis_[now-i]=0; 32 } 33 } 34 void DFS(int now,int total) 35 { 36 if(now==total) 37 { 38 DFS_(now); 39 return ; 40 } 41 for(int i=1; i<=n; ++i) 42 { 43 if(vis[now+i]||(now+i>tot)) continue; 44 vis[now+i]=1; 45 DFS(now+i,total); 46 vis[now+i]=0; 47 } 48 } 49 int work(int to) 50 { 51 ret=0; 52 memset(vis,0,sizeof(vis)); 53 memset(vis_,0,sizeof(vis_)); 54 vis[0]=1; DFS(0,to); 55 return ret; 56 } 57 58 int ret2; 59 bool vis2[N]; 60 void dfs(int now,int x) 61 { 62 if(now==x) 63 { 64 ret2++; 65 ret2%=mod; 66 return ; 67 } 68 for(int i=1; i<=n; ++i) 69 { 70 if(now+i<=x) dfs(now+i,x); 71 } 72 } 73 int work2(int x) 74 { 75 ret2=0; 76 memset(vis2,0,sizeof(vis2)); 77 dfs(0,x); 78 return ret2; 79 } 80 81 int AC() 82 { 83 freopen("stair.in","r",stdin); 84 freopen("stair.out","w",stdout); 85 86 int t; read(t); 87 for(; t--; ) 88 { 89 read(tot),read(n),read(m); 90 memset(f,0,sizeof(f)); 91 memset(a,0,sizeof(a)); 92 for(int i=0; i<m; ++i) f[i]=work(i); 93 for(int i=1; i<=m ;++i) a[i]=work2(i); 94 for(int i=m; i<=tot; ++i) 95 for(int j=1; j<=m; ++j) 96 f[i]=(f[i]+f[i-j]*a[j])%mod; 97 printf("%d\n",f[tot]); 98 } 99 return 0; 100 } 101 102 int Hope=AC(); 103 int main(){;}
考试的20分,46行的total被zz的我写成tot啊啊啊,然后就TLE了。。没用LL,啊啊啊
http://www.cnblogs.com/Shy-key/p/7484966.html 类似于这里走楼梯的状态方程。
f[i]+=f[i-j]*a[j],f[i]表示第一次走到i,第二次也走到i的方案数,
a[j]表示第二次走到j,第一次可以走的方案数。
需要先预处理f[i]的初始值,以及第二次走i步,第一次可以走的方案数。
1 #include <cstring> 2 #include <cstdio> 3 4 #define LL long long 5 6 const int mod(233333333); 7 const int N(400000+626); 8 int n,m,tot; 9 LL a[N],f[N]; 10 11 inline void read(int &x) 12 { 13 x=0; register char ch=getchar(); 14 for(;ch>‘9‘||ch<‘0‘;) ch=getchar(); 15 for(;ch>=‘0‘&&ch<=‘9‘;ch=getchar()) x=x*10+ch-‘0‘; 16 } 17 18 int ret; 19 bool vis[N],vis_[N]; 20 void DFS_(int now) 21 { 22 if(now==0) 23 { 24 ret++; 25 ret%=mod; 26 return ; 27 } 28 for(int i=1; i<=m; ++i) 29 { 30 if(vis_[now-i]||(now-i<0)) continue; 31 if(!vis[now-i]) continue; 32 vis_[now-i]=1; 33 DFS_(now-i); 34 vis_[now-i]=0; 35 } 36 } 37 void DFS(int now,int total) 38 { 39 if(now==total) 40 { 41 DFS_(now); 42 return ; 43 } 44 for(int i=1; i<=n; ++i) 45 { 46 if(vis[now+i]||(now+i>total)) continue; 47 vis[now+i]=1; 48 DFS(now+i,total); 49 vis[now+i]=0; 50 } 51 } 52 int work(int to) 53 { 54 ret=0; 55 memset(vis,0,sizeof(vis)); 56 memset(vis_,0,sizeof(vis_)); 57 vis[0]=1; DFS(0,to); 58 return ret; 59 } 60 61 int ret2; 62 bool vis2[N]; 63 void dfs(int now,int x) 64 { 65 if(now==x) 66 { 67 ret2++; 68 ret2%=mod; 69 return ; 70 } 71 for(int i=1; i<=n; ++i) 72 { 73 if(now+i<=x) dfs(now+i,x); 74 } 75 } 76 int work2(int x) 77 { 78 ret2=0; 79 memset(vis2,0,sizeof(vis2)); 80 dfs(0,x); 81 return ret2; 82 } 83 84 int AC() 85 { 86 freopen("stair.in","r",stdin); 87 freopen("stair.out","w",stdout); 88 89 int t; read(t); 90 for(; t--; ) 91 { 92 read(tot),read(n),read(m); 93 memset(f,0,sizeof(f)); 94 memset(a,0,sizeof(a)); 95 for(int i=0; i<m; ++i) f[i]=work(i); 96 for(int i=1; i<=m ;++i) a[i]=work2(i); 97 for(int i=m; i<=tot; ++i) 98 for(int j=1; j<=m; ++j) 99 f[i]=(f[i]+f[i-j]*a[j])%mod; 100 printf("%I64d\n",f[tot]); 101 } 102 return 0; 103 } 104 105 int Hope=AC(); 106 int main(){;}
AC
无奈、
T3 勤劳的蜜蜂 UVa808
1 #include <cstdio> 2 3 #define min(a,b) (a<b?a:b) 4 int a,b,dis[1026][1026]; 5 6 int AC() 7 { 8 freopen("beehive.in","r",stdin); 9 freopen("beehive.out","w",stdout); 10 11 for(int i=1; i<=10; ++i) 12 for(int j=1; j<=10; ++j) 13 dis[i][j]=(i!=j)*0x3f3f3f3f; 14 for(int i=2; i<8; ++i) dis[1][i]=dis[i][1]=1; 15 for(int i=7; i<11; ++i) dis[2][i]=dis[i][2]=1; 16 dis[3][2]=dis[2][3]=dis[3][4]=dis[4][3]=dis[4][5]=dis[5][4]=1; 17 dis[5][6]=dis[6][5]=dis[6][7]=dis[7][6]=dis[7][8]=dis[8][7]=1; 18 dis[8][2]=dis[2][8]=dis[8][9]=dis[9][8]=1; 19 dis[9][2]=dis[9][10]=1;dis[3][10]=dis[10][3]=1; 20 for(int k=1; k<=10; ++k) 21 for(int i=1; i<=10; ++i) 22 for(int j=1; j<=10; ++j) 23 dis[i][j]=min(dis[i][j],dis[i][k]+dis[k][j]); 24 for(; ~scanf("%d%d",&a,&b); ) 25 printf("%d %d %d\n",a,b,dis[a][b]); 26 return 0; 27 } 28 29 int Hope=AC(); 30 int main(){;}
打表10分。弃疗了