sgu256 dp
题意: 有一个做气球的机器。 现在想要做m个气球(m<=100), 一共有n个人(n<=10)可以做气球,每个人一分钟可以做fi个, 但是做完之后必须休息ti分钟,现在想要求出最少需要多少分钟可以做完这m个气球。
思路: 这道题开始的时候想了很多东西都是不对的。 主要是思路受干扰了。
这道题可以用dp, dp是这样的。dp[n][i][j][k][r]表示在第i秒结束时用的是第i个人, 上一秒用的是第j个人,以此类推。
这样就可以进行转化了。 这道题有一个很明显的特点就是数据量比较小。 所以可以维护一些可以处理小数据的东西。
其实上次的连连看的题目和这道题又很想的地方。
AC代码:
View Code
1 #include <cstdio> 2 #include <iostream> 3 #include <string> 4 #include <cstring> 5 using namespace std; 6 const int N = 505; 7 int dp[N][11][11][11][11]; 8 9 struct hh 10 { 11 int f, t; 12 } p[N]; 13 int n, m; 14 15 void init() 16 { 17 for(int i=1; i<=n; i++) 18 scanf("%d%d", &p[i].f, &p[i].t); 19 p[0].t = 0; 20 for(int i=0; i<N; i++) 21 for(int i1=0; i1<=10; i1++) 22 for(int i2=0; i2<=10; i2++) 23 for(int i3=0; i3<=10; i3++) 24 for(int i4=0; i4<=10; i4++) 25 dp[i][i1][i2][i3][i4] = -1000; 26 dp[0][0][0][0][0] = 0; 27 } 28 29 void solve() 30 { 31 bool used[12]; 32 int ans = N; 33 for(int i=0; i<N; i++) 34 { 35 for(int i1=0; i1<=n; i1++) 36 { 37 for(int i2=0; i2<=n; i2++) 38 { 39 for(int i3=0; i3<=n; i3++) 40 { 41 for(int i4=0; i4<=n; i4++) 42 { 43 if(dp[i][i1][i2][i3][i4] >= m) 44 { 45 printf("%d\n", i); 46 return ; 47 } 48 if(p[i2].t <= 1 && i2 != i1) 49 { 50 51 dp[i+1][i2][i1][i2][i3] = max( 52 dp[i+1][i2][i1][i2][i3], dp[i][i1][i2][i3][i4]+p[i2].f); 53 } 54 if(p[i3].t <= 2 && i3!=i1 && i3 != i2) 55 { 56 57 dp[i+1][i3][i1][i2][i3] = max( 58 dp[i+1][i3][i1][i2][i3], dp[i][i1][i2][i3][i4]+p[i3].f); 59 } 60 if(p[i4].t <= 3 && i4!=i1 && i4!=i2 && i4!=i3) 61 { 62 63 dp[i+1][i4][i1][i2][i3] = max( 64 dp[i+1][i4][i1][i2][i3], dp[i][i1][i2][i3][i4]+p[i4].f); 65 } 66 memset(used,0,sizeof(used)); 67 used[i1]=used[i2]=used[i3]=used[i4] = 1; 68 used[0] = 0; 69 for(int j=0; j<=n; j++) 70 { 71 if(used[j]) continue; 72 dp[i+1][j][i1][i2][i3] = max( 73 dp[i+1][j][i1][i2][i3], dp[i][i1][i2][i3][i4] + p[j].f); 74 } 75 } 76 } 77 } 78 } 79 } 80 } 81 82 int main() 83 { 84 while(scanf("%d%d", &m, &n) != EOF) 85 { 86 init(); 87 solve(); 88 } 89 return 0; 90 }


浙公网安备 33010602011771号