标签:技术 blog 最短路 isp stdout view 注意 log 题目
每天BBS都要从家里经过城市中的一段路到学校刷五三。城市中一共有n个路口和m条双向道路,每条双向道路都连接着两个路口ai、bi且有一定的时间花费vi。BBS家编号为1,学校编号为n。今天,BBS由于个人卫生综合征导致他很迟才离开家,他想用膜法改变k条道路的长度使通过其的时间花费vi变为0。现在他问你改变道路长度之后他到学校的最小时间花费是多少?
输入格式:
第一行为三个整数n、m、k,接下来的m行每行三个整数ai,bi,vi,分别表示这条路连着的两个路口和通过其所用的时间。
输出格式:
一个整数,表示BBS到学校的最小时间花费。
样例输入 |
样例输出 |
4 4 1 |
1 |
样例解释:
更新3->4的道路,最短路线为1->3->4,用时为1+0=1。
数据范围:
对于100%的数据:1<=n<=10000,1<=m<=50000,1<=k<=20,1<=vi<=1000000。
分层图建最短路——是最短路算法中的一种。
理解了最短路,分层图也好挺好理解的。
#include<iostream> #include<cstdio> #include<algorithm> #include<cstring> #include<queue> #include<vector> using namespace std; inline int read(){ int num=0,t=1;char c=getchar(); while(c>‘9‘||c<‘0‘){if(c==‘-‘)t=-1;c=getchar();} while(c>=‘0‘&&c<=‘9‘){num=(num<<1)+(num<<3)+c-‘0‘;c=getchar();} return num*t; } const int N=10010,INF=0x7fffffff; struct edge{int t,c;}; struct P{ int a,b,c; bool operator <(const P &hh)const{return c>hh.c;} }; vector<edge> g[N]; int d[N][30],n,m,k; void dij(int s){ priority_queue<P> q; memset(d,127,sizeof(d)); d[s][0]=0;q.push((P){s,0,0}); while(!q.empty()){ P p=q.top();q.pop(); int x=p.a,f=p.b,dis=p.c; for(int i=0;i<g[x].size();i++){ int y=g[x][i].t,c=g[x][i].c; if(f<k&&d[y][f+1]>dis){ d[y][f+1]=dis; q.push((P){y,f+1,d[y][f+1]}); } if(d[y][f]>dis+c){ d[y][f]=dis+c; q.push((P){y,f,d[y][f]}); } } } } int main() { freopen("school.in","r",stdin); freopen("school.out","w",stdout); n=read();m=read();k=read(); for(int i=1;i<=m;i++){ int a=read(),b=read(),c=read(); g[a].push_back((edge){b,c}); g[b].push_back((edge){a,c}); } dij(1); int ans=INF; for(int i=0;i<=k;i++) if(d[n][i]<ans)ans=d[n][i]; printf("%d\n",ans); return 0; }
LGL有一根长为n的木板。现在他想要把它砍成四段长度为整数的木板来做一个四边形,请问他有多少种不同的砍法?注意:四段长度为1、1、2、1和四段长度为1、2、1、1算两种砍法。
输入格式:
第一行为一个整数 n,表示木板的长度。
输出格式:
一个整数,不同的砍法数量。
样例输入 |
样例输出 |
6 |
6 |
样例解释:
1122,1212,1221,2112,2121,2211。
数据范围:
对于100%的数据:1<=n<=2500。
这题做法倒有挺多的,可以用通项公式推(真的难推),也可以DP(最容易的做法),甚至可以打表(打表打法好)。
这里考虑用DP的做法。dp[i][j]表示长度为i时分成j段的方案数,随便转移。
#include<cstdio> int n,half,f[2510][5]; int main() { freopen("quad.in","r",stdin); freopen("quad.out","w",stdout); scanf("%d",&n);f[0][0]=1; for(int i=1;i<=n;i++)for(int j=1;j<=4;j++){ int x=i<(n-1)/2?i:(n-1)/2; for(int k=1;k<=x;k++)f[i][j]+=f[i-k][j-1]; } printf("%d\n",f[n][4]); return 0; }
YYH有n道题要做。但是由于他上课做某些事,导致他一题都不会做,只好请LGL代打。LGL为了买自己心爱的坦克,他做第i题要收两笔钱:一笔在YYH叫他做题当天收,另外一笔在叫他做题的第二天收。YYH每天结束的时候都会把剩下的所有钱花光,然后再从父亲LRB处得到m元零花钱用来请LGL做题(也就是说,第一天的时候YYH是没有钱请LGL做题的,每一天用来请LGL做题所用的钱都是前一天LRB给的)。而且,YYH做的题目难度是循序渐进的:就算强如LGL,在做第i题之前也要先把第1到i-1题全部做完。请问YYH将所有题目做完并且把所有钱都付给LGL的最小天数。
输入格式:
第一行为两个整数m、n,接下来的n行每一行都有两个数ai和bi,分别表示LGL做第i题所收的两笔钱。
输出格式:
一个整数,表示最小天数。
样例输入 |
样例输出 |
100 5 |
6 |
样例解释:
第二天做1、2两题,第三天做3、4两题,第五天做5。在第六天的时候所有钱都付完。
数据范围:
对于100%的数据:1<=n<=300,1<=ai、bi<=m<=1000。
这题也是DP题。
dp[i][j]表示前i天做了j题后该天可能剩下的最多的钱的数量。
那么dp[i][j]可以转移到dp[i][j+1]、dp[i][j+2]……只要满足剩下的钱不少于0并且下个月的钱够还即可。
同时可以算出dp[i+1][j+1],dp[i+1][j+2]……最后输出满足dp[i][m]存在值的最小i。
#include<iostream> #include<cstdio> #include<algorithm> #include<cstring> using namespace std; inline int read(){ int t=1,num=0;char c=getchar(); while(c>‘9‘||c<‘0‘){if(c==‘-‘)t=-1;c=getchar();} while(c>=‘0‘&&c<=‘9‘){num=num*10+c-‘0‘;c=getchar();} return num*t; } int f[610][310],a[310],b[310]; int main() { freopen("solve.in","r",stdin); freopen("solve.out","w",stdout); int m,n;scanf("%d%d",&m,&n); for(int i=1;i<=n;i++)scanf("%d%d",&a[i],&b[i]); memset(f,-1,sizeof(f));f[2][0]=m; int i; for(i=2;f[i][n]==-1;i++){ for(int j=n;j>=0;j--) if(f[i][j]!=-1){ int k=j+1,t1=f[i][j],t2=f[i+1][j]=m; while(t1>=a[k]&&t2>=b[k]){ t1-=a[k];t2-=b[k]; f[i][k]=max(f[i][k],t1); f[i+1][k]=max(f[i+1][k],t2); k++; } } } printf("%d\n",i); return 0; }
给出一张有n个点和m条双向边的图,要求求出1到n的次短路的长度。一条边可以多次通过。
输入格式:
第一行为两个整数n和m。接下来的m行每行三个整数ai,bi,vi,分别表示这条路连着的两个点和他的长度。
输出格式:
一个整数,表示次短路的长度。
样例输入 |
样例输出 |
4 4 |
450 |
样例解释:
最短:1->2->4。
次短:1->2->3->4。
数据范围:
对于 100%的数据:1<=n、vi<=5000,1<=m<=100000。
这题显然就是裸的次短路啊。用dijstral解决。
#include<iostream> #include<vector> #include<queue> #include<cstring> #include<cstdio> using namespace std; inline int read(){ int num=0,t=1;char c=getchar(); while(c>‘9‘||c<‘0‘){if(c==‘-‘)t=-1;c=getchar();} while(c>=‘0‘&&c<=‘9‘){num=(num<<3)+(num<<1)+c-‘0‘;c=getchar();} return num*t; } const int maxn=5005,INF=1e9; int n,m,d[maxn],d2[maxn]; struct edge{int to,c;};vector<edge>g[maxn]; typedef pair<int,int>P; void add(int f,int t,int c){ g[f].push_back((edge){t,c}); g[t].push_back((edge){f,c}); } void solve(){ priority_queue< P,vector<P>,greater<P> >q; fill(d,d+n,INF);fill(d2,d2+n,INF); q.push(P(0,0));d[0]=0; while(!q.empty()) { P p=q.top();q.pop(); int v=p.second,dis=p.first; if(d2[v]<dis)continue; for(int i=0;i<g[v].size();i++){ edge e=g[v][i];int dis2=dis+e.c; if(d[e.to]>dis2) swap(d[e.to],dis2),q.push(P(d[e.to],e.to)); if(d2[e.to]>dis2&&d[e.to]<dis2) d2[e.to]=dis2,q.push(P(d2[e.to],e.to)); } } printf("%d\n",d2[n-1]); } int main(){ freopen("short.in","r",stdin); freopen("short.out","w",stdout); n=read();m=read(); for(int i=1;i<=m;i++){ int a=read(),b=read(),c=read();add(a-1,b-1,c); }solve(); return 0; }
本文由Yzyet编写,网址为www.cnblogs.com/Yzyet。非Yzyet同意,禁止转载,侵权者必究。
标签:技术 blog 最短路 isp stdout view 注意 log 题目
原文地址:http://www.cnblogs.com/Yzyet/p/7642686.html