2013年湖南省第九届程序设计大赛 I Interesting Calculator (dp)

来源:互联网 发布:暗物质与灵魂 知乎 编辑:程序博客网 时间:2024/05/17 15:40

题意:

给你一个x,y 给你三十个操作,每种操作的花费为c[i],求x变成y所需的最小花费和最小花费下的操作次数

 

方法:

          我最开始以后变成i的花费dp[i]= dp[i-j] + j变成i的花费, 后面wa很多次了之后才发现j不一定比i小

        因为有个操作是*0,递推的时候是从x递推到y,没有经过x变成0,0变成y, 所以这个操作会使得递推时出现错误;

       除去这个操作之外的所以操作都不会是的i变小

        所以我们只要算出x-y的解 和(x-0)操作+ 0-y操作的解,取最优的解即可 

 

代码:

#include <cstdio>#include <cstring>#define maxn 111111#define LL long longint A[33];LL  dp[maxn], d[maxn];int deal(int x, int t){if(t<= 10)return x*10+(t-1);else if(t<= 20)return x+(t-11);elsereturn x*(t-21);}int main(){//freopen("C:\\Users\\Monkey\\Desktop\\in.txt","r",stdin);//freopen("C:\\Users\\Monkey\\Desktop\\out1.txt","w",stdout);int T= 0;int x, y;while(scanf("%d %d",&x,&y)!=EOF){T++;for(int i= 1; i<= 30; i++)scanf("%d",&A[i]);memset(dp, -1, sizeof(dp));memset(d, 0, sizeof(d));dp[x]= 0;//printf("%d\n",deal(12,1));for(int i= x; i<= y; i++)if(dp[i]!= -1)for(int j= 1; j<= 30; j++){//printf()int k= deal(i, j);if(k<= y){if(dp[k]== -1){dp[k]= dp[i]+ A[j];d[k]= d[i] +1;}else {if(dp[i]+ A[j]< dp[k]){dp[k]= dp[i]+ A[j];d[k]= d[i] +1;}else if(dp[i] + A[j]== dp[k]){if(d[i]+1< d[k])d[k]= d[i]+ 1;}}}}LL ans1= dp[y], anst1= d[y];// x-y的所需花费 memset(dp, -1, sizeof(dp));memset(d, 0, sizeof(d));dp[0]= 0;for(int i= 0; i<= y; i++)if(dp[i]!= -1)for(int j= 1; j<= 30; j++){//printf()int k= deal(i, j);if(k<= y){if(dp[k]== -1){dp[k]= dp[i]+ A[j];d[k]= d[i] +1;}else {if(dp[i]+ A[j]< dp[k]){dp[k]= dp[i]+ A[j];d[k]= d[i] +1;}else if(dp[i] + A[j]== dp[k]){if(d[i]+1< d[k])d[k]= d[i]+ 1;}}}}LL ans2= dp[y] + A[21], anst2= d[y]+1;//x-0然后再0-y 的所需花费 LL ans, anst;if(ans1> ans2)ans= ans2, anst= anst2;else if(ans1< ans2)ans= ans1, anst= anst1;else {ans= ans1;anst= anst1< anst2? anst1: anst2;}printf("Case %d: %lld %lld\n",T,ans, anst);}return 0;}


 

 

                                   

                                        
0 0