zoukankan      html  css  js  c++  java
  • 3月18 周作业题解

    寒冰王座

    Time Limit : 2000/1000ms (Java/Other)   Memory Limit : 65536/32768K (Java/Other)
    Total Submission(s) : 38   Accepted Submission(s) : 18

    Font: Times New Roman | Verdana | Georgia

    Font Size: ← →

    Problem Description

    不死族的巫妖王发工资拉,死亡骑士拿到一张N元的钞票(记住,只有一张钞票),为了防止自己在战斗中频繁的死掉,他决定给自己买一些道具,于是他来到了地精商店前.

    死亡骑士:"我要买道具!"

    地精商人:"我们这里有三种道具,血瓶150块一个,魔法药200块一个,无敌药水350块一个."

    死亡骑士:"好的,给我一个血瓶."

    说完他掏出那张N元的大钞递给地精商人.

    地精商人:"我忘了提醒你了,我们这里没有找客人钱的习惯的,多的钱我们都当小费收了的,嘿嘿."

    死亡骑士:"......"

    死亡骑士想,与其把钱当小费送个他还不如自己多买一点道具,反正以后都要买的,早点买了放在家里也好,但是要尽量少让他赚小费.

    现在死亡骑士希望你能帮他计算一下,最少他要给地精商人多少小费.

    Input

    输入数据的第一行是一个整数T(1<=T<=100),代表测试数据的数量.然后是T行测试数据,每个测试数据只包含一个正整数N(1<=N<=10000),N代表死亡骑士手中钞票的面值.

    注意:地精商店只有题中描述的三种道具.

    Output

    对于每组测试数据,请你输出死亡骑士最少要浪费多少钱给地精商人作为小费.

    Sample Input

    2
    900
    250
    

    Sample Output

    0
    50
    

    思路:简单的完全背包,模板题。

    #include<iostream>
    #include<cstdio>
    #include<string>
    #include<vector>
    #include<cstring>
    #include<algorithm>
    #include<map>
    #include<set>
    
    using namespace std;
    
    int T;
    int n;
    int money[3]={150,200,350};
    int dp[10005];
    
    int main()
    {
        cin>>T;
        for(int i=0;i<3;i++){
                for(int j=money[i];j<10005;j++){
                    dp[j]=max(dp[j],dp[j-money[i]]+money[i]);
                }
            }
        while(T--)
        {
            cin>>n;
            cout<<n-dp[n]<<endl;
        }
        return 0;
    }

    悼念512汶川大地震遇难同胞——珍惜现在,感恩生活

    Time Limit : 1000/1000ms (Java/Other)   Memory Limit : 32768/32768K (Java/Other)
    Total Submission(s) : 70   Accepted Submission(s) : 11

    Font: Times New Roman | Verdana | Georgia

    Font Size: ← →

    Problem Description

    急!灾区的食物依然短缺!
    为了挽救灾区同胞的生命,心系灾区同胞的你准备自己采购一些粮食支援灾区,现在假设你一共有资金n元,而市场有m种大米,每种大米都是袋装产品,其价格不等,并且只能整袋购买。
    请问:你用有限的资金最多能采购多少公斤粮食呢?

    后记:
    人生是一个充满了变数的生命过程,天灾、人祸、病痛是我们生命历程中不可预知的威胁。
    月有阴晴圆缺,人有旦夕祸福,未来对于我们而言是一个未知数。那么,我们要做的就应该是珍惜现在,感恩生活——
    感谢父母,他们给予我们生命,抚养我们成人;
    感谢老师,他们授给我们知识,教我们做人
    感谢朋友,他们让我们感受到世界的温暖;
    感谢对手,他们令我们不断进取、努力。
    同样,我们也要感谢痛苦与艰辛带给我们的财富~

    Input

    输入数据首先包含一个正整数C,表示有C组测试用例,每组测试用例的第一行是两个整数n和m(1<=n<=100, 1<=m<=100),分别表示经费的金额和大米的种类,然后是m行数据,每行包含3个数p,h和c(1<=p<=20,1<=h<=200,1<=c<=20),分别表示每袋的价格、每袋的重量以及对应种类大米的袋数。

    Output

    对于每组测试数据,请输出能够购买大米的最多重量,你可以假设经费买不光所有的大米,并且经费你可以不用完。每个实例的输出占一行。

    Sample Input

    1
    8 2
    2 100 4
    4 100 2
    

    Sample Output

    400

    思路:多维背包,直接转换成01背包处理即可,推荐使用二进制优化,当然也可以简单的分成一件件(给出的代码就是最基本的转换方法)。

    #include<algorithm>
    #include<iostream>
    #include<algorithm>
    #include<cstring>
    
    using namespace std;
    #define M 10000
    
    int ans[M];
    int sale[M], wei[M], num[M];
    
    int main()
    {
        int T;
        int money, spe, count;
        cin >> T;
        while (T--)
        {
            memset(ans, 0, sizeof(ans));
    
            cin >> money >> spe;
            count = spe;
            for (int i = 1; i <= spe; i++)
            {
                cin >> sale[i] >> wei[i] >> num[i];
            }
    
            for (int i = 1; i <= spe; i++)
            {
                while (num[i]>1)
                {
                    num[i]--;
                    count++;
                    wei[count] = wei[i];
                    sale[count] = sale[i];
                }
            }
    
            for (int i = 1; i <= count; i++) {
                for (int j = money; j >= sale[i]; j--) {
                    ans[j] = max(ans[j], ans[j - sale[i]] + wei[i]);
                }
            }
            cout << ans[money] << endl;
        }
        return 0;
    }

    湫湫系列故事——减肥记I

    Time Limit : 3000/1000ms (Java/Other)   Memory Limit : 65535/32768K (Java/Other)
    Total Submission(s) : 19   Accepted Submission(s) : 9

    Font: Times New Roman | Verdana | Georgia

    Font Size: ← →

    Problem Description

      对于吃货来说,过年最幸福的事就是吃了,没有之一!
      但是对于女生来说,卡路里(热量)是天敌啊!
      资深美女湫湫深谙“胖来如山倒,胖去如抽丝”的道理,所以她希望你能帮忙制定一个食谱,能使她吃得开心的同时,不会制造太多的天敌。

      当然,为了方便你制作食谱,湫湫给了你每日食物清单,上面描述了当天她想吃的每种食物能带给她的幸福程度,以及会增加的卡路里量。

    Input

      输入包含多组测试用例。
      每组数据以一个整数n开始,表示每天的食物清单有n种食物。
      接下来n行,每行两个整数a和b,其中a表示这种食物可以带给湫湫的幸福值(数值越大,越幸福),b表示湫湫吃这种食物会吸收的卡路里量。
      最后是一个整数m,表示湫湫一天吸收的卡路里不能超过m。

      [Technical Specification]
      1. 1 <= n <= 100
      2. 0 <= a,b <= 100000
      3. 1 <= m <= 100000

    Output

      对每份清单,输出一个整数,即满足卡路里吸收量的同时,湫湫可获得的最大幸福值。

    Sample Input

    3
    3 3
    7 7
    9 9
    10
    5
    1 1
    5 3
    10 3
    6 8
    7 5
    6
    

    Sample Output

    10
    20
    

    思路:还是完全背包。。。。。

    #include<algorithm>
    #include<iostream>
    #include<cstring>
    
    using namespace std;
    
    int n,limit;
    int dp[100005];
    struct Data
    {
        int get;
        int out;
    }food[105];
    
    
    int main()
    {
        while(cin>>n)
        {
            memset(dp,0,sizeof(dp));
            for(int i=1;i<=n;i++){
                cin>>food[i].get>>food[i].out;
            }
            cin>>limit;
            for(int i=1;i<=n;i++){
                for(int j=food[i].out;j<=limit;j++){
                    dp[j]=max(dp[j],dp[j-food[i].out]+food[i].get);
                }
            }
            cout<<dp[limit]<<endl;
        }
        
        return 0;
    }

    畅通工程

    Time Limit : 4000/2000ms (Java/Other)   Memory Limit : 65536/32768K (Java/Other)
    Total Submission(s) : 17   Accepted Submission(s) : 8

    Font: Times New Roman | Verdana | Georgia

    Font Size: ← →

    Problem Description

    某省调查城镇交通状况,得到现有城镇道路统计表,表中列出了每条道路直接连通的城镇。省政府“畅通工程”的目标是使全省任何两个城镇间都可以实现交通(但不一定有直接的道路相连,只要互相间接通过道路可达即可)。问最少还需要建设多少条道路?

    Input

    测试输入包含若干测试用例。每个测试用例的第1行给出两个正整数,分别是城镇数目N ( < 1000 )和道路数目M;随后的M行对应M条道路,每行给出一对正整数,分别是该条道路直接连通的两个城镇的编号。为简单起见,城镇从1到N编号。
    注意:两个城市之间可以有多条道路相通,也就是说
    3 3
    1 2
    1 2
    2 1
    这种输入也是合法的
    当N为0时,输入结束,该用例不被处理。

    Output

    对每个测试用例,在1行里输出最少还需要建设的道路数目。

    Sample Input

    4 2
    1 3
    4 3
    3 3
    1 2
    1 3
    2 3
    5 2
    1 2
    3 5
    999 0
    0
    

    Sample Output

    1
    0
    2
    998
    

    Hint

    Hint
    Huge input, scanf is recommended. 

     
    思路:考察并查集的掌握,记得结尾-1就可以,因为n个版块连接只需要n-1条路
     
    #include<algorithm>
    #include<iostream>
    #include<cstring>
    #include<cstdio>
    
    using namespace std;
    
    int ans;
    int n,m;
    int u,v;
    int boss[1010];
    
    void init()
    {
        ans=0;
        for(int i=0;i<=n;i++){
            boss[i]=i;
        }
    }
    
    int find(int k)
    {
        if(boss[k]==k){
            return k;
        }
        boss[k]=find(boss[k]);
        return boss[k];
    }
    
    void mercy(int x,int y)
    {
        int t_1,t_2;
        t_1=find(x);
        t_2=find(y);
        if(t_1>t_2){
            boss[t_2]=t_1;
        }
        else{
            boss[t_1]=t_2;
        }
    }
    
    
    int main()
    {
        while(scanf("%d",&n)!=EOF && n)
        {
            cin>>m;
            init();
            for(int i=1;i<=m;i++){
                cin>>u>>v;
                mercy(u,v);
            }
            for(int i=1;i<=n;i++){
                if(boss[i]==i){
                    ans++;
                }
            }
            cout<<ans-1<<endl;
        }
        return 0;
    }

    还是畅通工程

    Time Limit : 4000/2000ms (Java/Other)   Memory Limit : 65536/32768K (Java/Other)
    Total Submission(s) : 22   Accepted Submission(s) : 6

    Font: Times New Roman | Verdana | Georgia

    Font Size: ← →

    Problem Description

    某省调查乡村交通状况,得到的统计表中列出了任意两村庄间的距离。省政府“畅通工程”的目标是使全省任何两个村庄间都可以实现公路交通(但不一定有直接的公路相连,只要能间接通过公路可达即可),并要求铺设的公路总长度为最小。请计算最小的公路总长度。

    Input

    测试输入包含若干测试用例。每个测试用例的第1行给出村庄数目N ( < 100 );随后的N(N-1)/2行对应村庄间的距离,每行给出一对正整数,分别是两个村庄的编号,以及此两村庄间的距离。为简单起见,村庄从1到N编号。
    当N为0时,输入结束,该用例不被处理。

    Output

    对每个测试用例,在1行里输出最小的公路总长度。

    Sample Input

    3
    1 2 1
    1 3 2
    2 3 4
    4
    1 2 1
    1 3 4
    1 4 1
    2 3 3
    2 4 2
    3 4 5
    0
    

    Sample Output

    3
    5
    

    Hint

    Hint
    Huge input, scanf is recommended. 
     
    思路:考察最小生成树
     
    #include<algorithm>
    #include<iostream>
    #include<cstring>
    #include<cstdio>
    
    using namespace std;
    
    int n;
    int m;
    int ans;
    int Count;
    int boss[100];
    struct Data
    {
        int u;
        int v;
        int len;
    }load[5000];
    
    void init()
    {
        ans=Count=0;
        m=n*(n-1)/2;
        for(int i=1;i<=n;i++){
            boss[i]=i;
        }
    }
    
    int cmp(Data &a,Data &b)
    {
        return a.len<b.len;
    }
    
    int find(int k)
    {
        if(boss[k]==k)
        {
            return k;
        }
        boss[k]=find(boss[k]);
        return boss[k];
    }
    
    void mercy(int x,int y)
    {
        int t_1,t_2;
        t_1=find(x);
        t_2=find(y);
        if(t_1!=t_2)
        {
            boss[t_2]=t_1;
        }
    }
    
    int main()
    {
        while(scanf("%d",&n)!=EOF && n)
        {
            init();
            for(int i=1;i<=m;i++){
                cin>>load[i].u>>load[i].v>>load[i].len;
            }
            sort(load+1,load+m+1,cmp);
            for(int i=1;i<=m;i++){
                if(find(load[i].u)!=find(load[i].v)){
                    mercy(load[i].u,load[i].v);
                    ans+=load[i].len;
                    Count++;
                }
                if(Count==n-1){
                    break;
                }
            }
            cout<<ans<<endl;
        }
        
        return 0;
    }

    继续畅通工程

    Time Limit : 2000/1000ms (Java/Other)   Memory Limit : 32768/32768K (Java/Other)
    Total Submission(s) : 10   Accepted Submission(s) : 5

    Font: Times New Roman | Verdana | Georgia

    Font Size: ← →

    Problem Description

    省政府“畅通工程”的目标是使全省任何两个村庄间都可以实现公路交通(但不一定有直接的公路相连,只要能间接通过公路可达即可)。现得到城镇道路统计表,表中列出了任意两城镇间修建道路的费用,以及该道路是否已经修通的状态。现请你编写程序,计算出全省畅通需要的最低成本。

    Input

    测试输入包含若干测试用例。每个测试用例的第1行给出村庄数目N ( 1< N < 100 );随后的 N(N-1)/2 行对应村庄间道路的成本及修建状态,每行给4个正整数,分别是两个村庄的编号(从1编号到N),此两村庄间道路的成本,以及修建状态:1表示已建,0表示未建。

    当N为0时输入结束。

    Output

    每个测试用例的输出占一行,输出全省畅通需要的最低成本。

    Sample Input

    3
    1 2 1 0
    1 3 2 0
    2 3 4 0
    3
    1 2 1 0
    1 3 2 0
    2 3 4 1
    3
    1 2 1 0
    1 3 2 1
    2 3 4 1
    0

    Sample Output

    3
    1
    0

    思路:依然是最小生成树,不过有些路已经修好,那就先把这些路排在前面,然后成本设置为0就可以了。

    #include<algorithm>
    #include<iostream>
    #include<cstring>
    #include<cstdio>
    
    using namespace std;
    
    int n;
    int m;
    int ans;
    int Count;
    int boss[100];
    struct Data
    {
        int ok;
        int u;
        int v;
        int len;
    }load[5000];
    
    void init()
    {
        ans=Count=0;
        m=n*(n-1)/2;
        for(int i=1;i<=n;i++){
            boss[i]=i;
        }
    }
    
    int cmp(Data &a,Data &b)
    {
        if(a.ok==b.ok){
            return a.len<b.len;
        }
        else{
            return a.ok<b.ok;
        }
    }
    
    int find(int k)
    {
        if(boss[k]==k)
        {
            return k;
        }
        boss[k]=find(boss[k]);
        return boss[k];
    }
    
    void mercy(int x,int y)
    {
        int t_1,t_2;
        t_1=find(x);
        t_2=find(y);
        if(t_1!=t_2)
        {
            boss[t_2]=t_1;
        }
    }
    
    int main()
    {
        while(scanf("%d",&n)!=EOF && n)
        {
            init();
            for(int i=1;i<=m;i++){
                scanf("%d%d%d%d",&load[i].u,&load[i].v,&load[i].len,&load[i].ok);
                if(load[i].ok){
                    mercy(load[i].u,load[i].v);
                }
            }
            
            sort(load+1,load+m+1,cmp);
            
            for(int i=1;i<=m;i++){
                if(load[i].ok==1){break;}
                if(find(load[i].u)!=find(load[i].v)){
                    mercy(load[i].u,load[i].v);
                //    cout<<load[i].u<<' '<<load[i].v<<' '<<load[i].len<<endl;
                    ans+=load[i].len;
                    Count++;
                }
                if(Count==n-1){
                    break;
                }
            }
            cout<<ans<<endl;
        }
        return 0;
    }

    畅通工程续

    Time Limit : 3000/1000ms (Java/Other)   Memory Limit : 32768/32768K (Java/Other)
    Total Submission(s) : 5   Accepted Submission(s) : 2

    Font: Times New Roman | Verdana | Georgia

    Font Size: ← →

    Problem Description

    某省自从实行了很多年的畅通工程计划后,终于修建了很多路。不过路多了也不好,每次要从一个城镇到另一个城镇时,都有许多种道路方案可以选择,而某些方案要比另一些方案行走的距离要短很多。这让行人很困扰。

    现在,已知起点和终点,请你计算出要从起点到终点,最短需要行走多少距离。

    Input

    本题目包含多组数据,请处理到文件结束。
    每组数据第一行包含两个正整数N和M(0<N<200,0<M<1000),分别代表现有城镇的数目和已修建的道路的数目。城镇分别以0~N-1编号。
    接下来是M行道路信息。每一行有三个整数A,B,X(0<=A,B<N,A!=B,0<X<10000),表示城镇A和城镇B之间有一条长度为X的双向道路。
    再接下一行有两个整数S,T(0<=S,T<N),分别代表起点和终点。

    Output

    对于每组数据,请在一行里输出最短需要行走的距离。如果不存在从S到T的路线,就输出-1.

    Sample Input

    3 3
    0 1 1
    0 2 3
    1 2 1
    0 2
    3 1
    0 1 1
    1 2

    Sample Output

    2
    -1

    思路:最短路练习,有Dijkstra算法,Bellman-Ford算法,Floyd算法和SPFA算法都能解决,下面用到是Floyd算法(简单实现但是容易超时)

    #include<iostream>
    #include<algorithm>
    using namespace std;
    #define inf 100000
    #define M 2005
    
    int n, m;
    int st, ed;
    int u, v, len;
    int Map[M][M];
    
    void init()
    {
        for (int i = 0; i <= n; i++) {
            for (int j = 0; j <= n; j++) {
                if (i == j) {
                    Map[i][j] = 0;
                }
                else {
                    Map[i][j] = inf;
                }
            }
        }
    }
    
    int main()
    {
        while (scanf("%d%d",&n,&m)!=EOF)
        {
            init();
            for (int i = 1; i <= m; i++) {
                cin >> u >> v >> len;
                if (Map[u][v] > len) {
                    Map[u][v] = len;
                    Map[v][u] = len;
                }
            }
            cin >> st >> ed;
            for (int k = 0; k < n; k++) {
                for (int i = 0; i < n; i++) {
                    for (int j = 0; j < n; j++) {
                        if (Map[i][j] > Map[i][k] + Map[k][j]) {
                            Map[i][j] = Map[i][k] + Map[k][j];
                        }
                    }
                }
            }
            if (Map[st][ed] == inf) {
                cout << -1 << endl;
            }
            else {
                cout << Map[st][ed] << endl;
            }
        }
        return 0;
    }

    一个人的旅行

    Time Limit : 1000/1000ms (Java/Other)   Memory Limit : 32768/32768K (Java/Other)
    Total Submission(s) : 3   Accepted Submission(s) : 2

    Font: Times New Roman | Verdana | Georgia

    Font Size: ← →

    Problem Description

    虽然草儿是个路痴(就是在杭电待了一年多,居然还会在校园里迷路的人,汗~),但是草儿仍然很喜欢旅行,因为在旅途中 会遇见很多人(白马王子,^0^),很多事,还能丰富自己的阅历,还可以看美丽的风景……草儿想去很多地方,她想要去东京铁塔看夜景,去威尼斯看电影,去阳明山上看海芋,去纽约纯粹看雪景,去巴黎喝咖啡写信,去北京探望孟姜女……眼看寒假就快到了,这么一大段时间,可不能浪费啊,一定要给自己好好的放个假,可是也不能荒废了训练啊,所以草儿决定在要在最短的时间去一个自己想去的地方!因为草儿的家在一个小镇上,没有火车经过,所以她只能去邻近的城市坐火车(好可怜啊~)。

    Input

    输入数据有多组,每组的第一行是三个整数T,S和D,表示有T条路,和草儿家相邻的城市的有S个,草儿想去的地方有D个;
    接着有T行,每行有三个整数a,b,time,表示a,b城市之间的车程是time小时;(1=<(a,b)<=1000;a,b 之间可能有多条路)
    接着的第T+1行有S个数,表示和草儿家相连的城市;
    接着的第T+2行有D个数,表示草儿想去地方。

    Output

    输出草儿能去某个喜欢的城市的最短时间。

    Sample Input

    6 2 3
    1 3 5
    1 4 7
    2 8 12
    3 8 4
    4 9 12
    9 10 2
    1 2
    8 9 10

    Sample Output

    9

    思路:依然是最短路练习,保存下附近城市和目的城市,后面再比较一下距离就可以了。

    #include <iostream>
    #include<algorithm>
    #include<cstdio>
    
    using namespace std;
    #define M 1010
    #define inf 0x3f3f3f3f
    
    int n;
    int ans;
    int T, S, D;
    int u, v, w;
    int Map[M][M];
    int Nei[M], Aim[M];
    
    
    void init()
    {
        n = 0;
        ans = inf;
        for (int i = 1; i <= 1000; i++) {
            for (int j = 1; j <= 1000; j++) {
                if (i == j) { Map[i][j] = Map[j][i] = 0; }
                else{ Map[i][j] = Map[j][i] = inf; }
            }
        }
    }
    
    void Get_data()
    {
        for (int i = 1; i <= T; i++) {
            scanf("%d%d%d", &u, &v, &w);
            if (Map[u][v] > w) {
                Map[u][v] = Map[v][u] = w;
            }
            n = max(n, max(u, v));
        }
        for (int i = 1; i <= S; i++) {
            scanf("%d", &Nei[i]);
        }
        for (int i = 1; i <= D; i++) {
            scanf("%d", &Aim[i]);
        }
    }
    
    void Dis_data()
    {
        for (int k = 1; k <= n; k++) {
            for (int i = 1; i <= n; i++) {
                if (Map[i][k] == inf) { continue; }
                for (int j = 1; j <= n; j++) {
                    if (i == j) { continue; }
                    if (Map[k][j] == inf) { continue; }
                    if (Map[i][j] > Map[i][k] + Map[k][j]) {
                        Map[i][j] = Map[i][k] + Map[k][j];
                        Map[j][i] = Map[i][j];
                    }
                }
            }
        }
    }
    
    void Ans_data()
    {
        for (int i = 1; i <= S; i++) {
            for (int j = 1; j <= D; j++) {
                ans = min(ans, Map[Nei[i]][Aim[j]]);
            }
        }
        cout << ans << endl;
    }
    
    int main()
    {
        while (scanf("%d%d%d", &T, &S, &D) != EOF)
        {
            init();
            Get_data();
            Dis_data();
            Ans_data();
        }
        return 0;
    }



  • 相关阅读:
    hdu 1142 用优先队列实现Dijkstra
    POJ 2063 Investment 完全背包
    POJ 3260 多重背包+完全背包
    bignum 大数模板
    POJ 3468(树状数组的威力)
    POJ 3468 线段树裸题
    hdu 1058 Humble Numbers
    CodeForces 185A 快速幂
    POJ 1990 MooFest 树状数组
    设计模式(20)策略模式
  • 原文地址:https://www.cnblogs.com/caibingxu/p/10553804.html
Copyright © 2011-2022 走看看