USACO section 3.4 Raucous Rockers(dp)

Raucous Rockers

You just inherited the rights to N (1 <= N <= 20) previously unreleased songs recorded by the popular group Raucous Rockers. You plan to release a set of M (1 <= M <= 20) compact disks with a selection of these songs. Each disk can hold a maximum of T (1 <= T <= 20) minutes of music, and a song can not overlap from one disk to another.

Since you are a classical music fan and have no way to judge the artistic merits of these songs, you decide on the following criteria for making the selection:

  • The songs on the set of disks must appear in the order of the dates that they were written.
  • The total number of songs included will be maximized.

PROGRAM NAME: rockers

INPUT FORMAT

Line 1:Three integers: N, T, and M.
Line 2:N integers that are the lengths of the songs ordered by the date they were written.

SAMPLE INPUT (file rockers.in)

4 5 2
4 3 4 2

OUTPUT FORMAT

A single line with an integer that is the number of songs that will fit on M disks.

SAMPLE OUTPUT (file rockers.out)

3

思路:枚举所有状态

/*
ID:nealgav1
LANG:C++
PROG:rockers
*/
#include<fstream>
#include<cstring>
using namespace std;
ifstream cin("rockers.in");
ofstream cout("rockers.out");
const int mm=33;
class node
{
  public:int t,c;
  node(){t=c=0;}
}dp[mm][mm];
int n,t,m;
int s[mm];
int main()
{
  while(cin>>n>>t>>m)
  { int ans=0;
    for(int i=0;i<n;i++)
      cin>>s[i];
    int z=1<<n;
    int tt,num,za;
    for(int i=0;i<z;i++)
    { tt=t;num=m-1;bool flag=0;za=0;
      for(int j=0;j<n&&!flag;j++)
        {
          if(i&(1<<j))
          {
            ++za;
            if(tt-s[j]>=0)tt-=s[j];
            else if(num)
            {
              --num;tt=t-s[j];
              if(tt<0)flag=1;
            }
            else flag=1;
          }
        }
        if(!flag&&za>ans)ans=za;
    }
    cout<<ans<<"\n";
  }
}

DP 背包


/*
ID:nealgav1
LANG:C++
PROG:rockers
*/
#include<fstream>
#include<cstring>
using namespace std;
ifstream cin("rockers.in");
ofstream cout("rockers.out");
const int mm=110;
int dp[mm][mm],tt[mm],ma[mm];
int n,t,m;
int main()
{
  while(cin>>n>>t>>m)
  {
    memset(dp,0,sizeof(dp));
    memset(ma,0,sizeof(ma));
    for(int i=0;i<n;i++)cin>>tt[i];
    for(int i=0;i<n;i++)
    {
      for(int j=m;j>=1;j--)
      { dp[j][0]=ma[j-1];///ma[j-1]代表j-1个盘最多装的歌曲数,后面更新第j个盘
        for(int k=t;k>=tt[i];--k)///背包,把第i首歌放入背包
          if(dp[j][k]<dp[j][k-tt[i]]+1)
        {
          dp[j][k]=dp[j][k-tt[i]]+1;
          ma[j]=ma[j]>dp[j][k]?ma[j]:dp[j][k];
        }
      }
    }
    cout<<ma[m]<<"\n";
  }
}


   Test 1: TEST OK [0.000 secs, 3404 KB]
   Test 2: TEST OK [0.000 secs, 3404 KB]
   Test 3: TEST OK [0.000 secs, 3404 KB]
   Test 4: TEST OK [0.000 secs, 3404 KB]
   Test 5: TEST OK [0.000 secs, 3404 KB]
   Test 6: TEST OK [0.000 secs, 3404 KB]
   Test 7: TEST OK [0.000 secs, 3404 KB]
   Test 8: TEST OK [0.000 secs, 3404 KB]
   Test 9: TEST OK [0.000 secs, 3404 KB]
   Test 10: TEST OK [0.000 secs, 3404 KB]
   Test 11: TEST OK [0.000 secs, 3404 KB]
   Test 12: TEST OK [0.000 secs, 3404 KB]



USER: Neal Gavin Gavin [nealgav1]
TASK: rockers
LANG: C++

Compiling...
Compile: OK

Executing...
   Test 1: TEST OK [0.000 secs, 3364 KB]
   Test 2: TEST OK [0.000 secs, 3364 KB]
   Test 3: TEST OK [0.000 secs, 3364 KB]
   Test 4: TEST OK [0.000 secs, 3364 KB]
   Test 5: TEST OK [0.000 secs, 3364 KB]
   Test 6: TEST OK [0.000 secs, 3364 KB]
   Test 7: TEST OK [0.032 secs, 3364 KB]
   Test 8: TEST OK [0.162 secs, 3364 KB]
   Test 9: TEST OK [0.032 secs, 3364 KB]
   Test 10: TEST OK [0.000 secs, 3364 KB]
   Test 11: TEST OK [0.151 secs, 3364 KB]
   Test 12: TEST OK [0.162 secs, 3364 KB]

All tests OK.

YOUR PROGRAM ('rockers') WORKED FIRST TIME! That's fantastic -- and a rare thing. Please accept these special automated congratulations.

Here are the test data inputs:

------- test 1 ----
4 5 2
4 2 4 3
------- test 2 ----
1 1 5
6
------- test 3 ----
10 5 5
5 3 5 3 5 3 5 3 5 2
------- test 4 ----
10 10 9
9 7 8 6 10 9 8 6 5 9
------- test 5 ----
9 15 4
15 7 8 6 9 5 10 4 11
------- test 6 ----
15 10 1
3 6 7 9 6 8 6 7 5 8 10 7 6 3 4
------- test 7 ----
20 20 2
10 15 19 18 11 15 14 16 12 14 15 10 10 16 14 16 14 15 16 10
------- test 8 ----
20 20 10
18 15 16 10 2 20 14 17 3 7 16 15 18 16 20 16 13 9 4 16
------- test 9 ----
18 10 6
4 9 6 3 9 7 6 9 4 1 10 9 5 8 5 4 7 6
------- test 10 ----
10 10 20
8 3 6 4 10 8 2 9 5 10
------- test 11 ----
20 20 5
4 9 2 19 5 3 10 15 18 4 3 9 14 17 1 20 15 19 12 6
------- test 12 ----
20 20 10
19 15 1 5 6 19 15 18 13 19 18 5 3 6 2 6 19 13 15 16
Keep up the good work!
Thanks for your submission!

Raucous Rockers
Brian Jacokes

This is a pretty straight-forward dynamic programming problem. The factors that determine whether we can put a song on a CD are:

  • The length used up on the CD so far
  • The length of the current song
  • The last song that we put on the CD (because of the date restriction)

Therefore, we create an matrix called "dp", with dp[a][b][c] being the most number of songs that we can put on the first 'a' CDs, with 'b' minutes already used up on the 'a'th CD, and with 'c' being the last song that we put on CD 'a'. We initialize the matrix to be all zeroes, and then we cycle through it as follows:

  • We traverse the CDs in ascending order to satisfy the date requirement
  • We go through the number of minutes used in ascending order, so that we have had a chance to put on a song earlier in the CD before we try to put songs on at a later time
  • We go through the last song used in ascending order (although this order doesn't really matter)
  • We go through the new songs in ascending order, making sure to start with songs that were dated after the last song

If the new song that we want to include in the set will fit on the current CD, there is no reason to put it on the next CD, so we check the matrix and see if adding it to the current set of songs will be better than the value already stored in the matrix. Otherwise, we check to see if it would be beneficial to put the song on the next CD. As a time-saver, each time we check a current value in the matrix to see what other songs we can put on the CD, we also check and see if this value is better than the most number of CDs that we have currently been able to fit in the set, so that we don't need to do this at the end. Finally, we output this best number, which will be the most number of CDs that we can fit in the set.

#include <stdio.h>
#define MAX 25

int     dp[MAX][MAX][MAX], length[MAX];

int 
main ()
{
    FILE   *in = fopen ("rockers.in", "r");
    FILE   *out = fopen ("rockers.out", "w");
    int     a, b, c, d, best, numsongs, cdlength, numcds;
    fscanf (in, "%d%d%d", &numsongs, &cdlength, &numcds);
    for (a = 1; a <= numsongs; a++)
	fscanf (in, "%d", &length[a]);
    best = 0;
    for (a = 0; a < numcds; a++)/* current cd */
	for (b = 0; b <= cdlength; b++)	/* number of minutes used */
	    for (c = 0; c <= numsongs; c++) {	/* last song */
		for (d = c + 1; d <= numsongs; d++) {	/* new song */
		    if (b + length[d] <= cdlength) {
			if (dp[a][b][c] + 1 > dp[a][b + length[d]][d])
			    dp[a][b + length[d]][d] = dp[a][b][c] + 1;
		    }
		    else {
			if (dp[a][b][c] + 1 > dp[a + 1][length[d]][d])
			    dp[a + 1][length[d]][d] = dp[a][b][c] + 1;
		    }
		}
		if (dp[a][b][c] > best)
		    best = dp[a][b][c];
	    }
    fprintf (out, "%d\n", best);
    return 0;
}

转载于:https://www.cnblogs.com/nealgavin/archive/2013/03/13/3206128.html

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值