$NOIP1999$ 题解报告
目录
•$Luogu\ P1016$ 旅行家的预算$(\ √\ )$
•$Luogu\ P1021$ 邮票面值设计$(\ √\ )$
$Luogu\ P1016$ 旅行家的预算
每次寻找从当前加油站往后走能到达的最近的一个价格比当前低的加油站,并去往这个加油站。
加满油后能到达的所有加油站中没有油价比当前低的,就找到一个油价最低的。
1 #include<bits/stdc++.h> 2 using namespace std; 3 double ans=0,num,D1,C,D2,P,N,l=0; 4 int next; 5 double d[8],p[8]; 6 double compare(int x){ 7 for(int j=x+1;j<=N&&d[j]<=d[x]+C*D2;j++) 8 if(p[j]<p[x]) {next=j;return (d[j]-d[x]);} 9 return 0; 10 } 11 int minn(int x){ 12 double least=123456,mi; 13 for(int j=x+1;j<=N&&d[j]<=d[x]+C*D2;j++) 14 if(p[j]<least) least=p[j],mi=j; 15 return mi; 16 } 17 int main(){ 18 int i; 19 scanf("%lf%lf%lf%lf%lf",&D1,&C,&D2,&P,&N); 20 d[0]=0;p[0]=P; 21 for(i=1;i<=N;i++) 22 scanf("%lf%lf",&d[i],&p[i]); 23 if(N==0&&D1>D2*C){printf("No Solution");return 0;} 24 for(i=0;i<=N;i=next){ 25 double t=compare(i); 26 if(t){ 27 num=(t/D2-l)*p[i];l=0;ans+=num; 28 continue; 29 } 30 if(d[i]+C*D2>=D1){ 31 num=((D1-d[i])/D2-l)*p[i];ans+=num; 32 break; 33 } 34 next=minn(i); 35 if(next==0){printf("No Solution");return 0;} 36 num=(C-l)*p[i]; 37 l=C-(d[next]-d[i])/D2; 38 ans+=num; 39 } 40 printf("%.2lf",ans); 41 return 0; 42 }
$Luogu\ P1021$ 邮票面值设计
我们枚举每种邮票可能的面值,直接单调递增地枚举,下界为上一种邮票的面值$+1$,上界为当前状态下能连续表示出的最大值$+1$
每次$DP$求能连续表示出的最大值,$f[i]$为表示出$i$所需要的最小邮票数,统计从$1$开始连续的$f<=n$的个数。
1 #include<bits/stdc++.h> 2 #define ri register int 3 #define ll long long 4 #define rl register ll 5 #define go(i,a,b) for(ri i=a;i<=b;i++) 6 #define back(i,a,b) for(ri i=a;i>=b;i--) 7 #define g() getchar() 8 #define il inline 9 #define pf printf 10 #define mem(a,b) memset(a,b,sizeof(a)) 11 using namespace std; 12 il int fr(){ 13 ri w=0,q=1;char ch=g(); 14 while(ch<'0'||ch>'9'){if(ch=='-')q=-1;ch=g();} 15 while(ch>='0'&&ch<='9')w=(w<<1)+(w<<3)+ch-'0',ch=g(); 16 return w*q; 17 } 18 const int N=2002; 19 int n,k,f[N],a[20],as[20],ans; 20 il int cal(ri x,ri num){ 21 mem(f,0x3f);f[0]=0; 22 go(i,1,x)go(j,a[i],num*n)f[j]=min(f[j],f[j-a[i]]+1); 23 go(i,1,n*num)if(f[i]>n)return i-1; 24 } 25 il void work(ri x,ri lst,ri mx){ 26 if(x>k){if(mx>ans){ans=mx;go(i,1,k)as[i]=a[i];}return;} 27 go(i,lst+1,mx+1){ 28 a[x]=i;ri sum=cal(x,i); 29 work(x+1,i,sum); 30 } 31 return; 32 } 33 int main(){ 34 //freopen(".in","r",stdin); 35 //freopen(".out","w",stdout); 36 n=fr();k=fr(); 37 work(1,0,0); 38 go(i,1,k)pf("%d ",as[i]);puts(""); 39 pf("MAX=%d\n",ans); 40 return 0; 41 }