Description
Input
Output
Sample Input
2 3 Computer 3 3 English 20 1 Math 3 2 3 Computer 3 3 English 6 3 Math 6 3
Sample Output
2 Computer Math English 3 Computer English Math
Hint
In the second test case, both Computer->English->Math and Computer->Math->English leads to reduce 3 points, but the word "English" appears earlier than the word "Math", so we choose the first order. That is so-called alphabet order.
给出了n门作业,每科做也的提交时间和需要时间,每超过一天罚1分,问最少罚几分,要求最小字典序
状态表示,在n科中做了哪几科,二进制数中第i个为1表示做了第i科,dp[i]表示状态为i时的最少罚时,和已经用了的分数
状态转移方程从科目为j的转移到科目为j+1的
为保证字典序最小,所以要让dp[i]尽量有更小的i来得到。
#include <cstdio>
#include <cstring>
#include <algorithm>
using namespace std ;
struct node
{
char s[120] ;
int d , c ;
} p[20];
int state[20][7000] , num[20] , c[20] , cnt ;
int dp1[20][7000] , dp2[20][7000] , step[20][7000] ; //dp[i][j][]写i科作业在状态j时,0代表超出的时间,1代表需要的时间。
int find1(int x,int i)
{
//printf("x == %d i == %d\n", x, i) ;
int low = 0 , mid , high = num[i]-1 ;
while( low <= high )
{
mid = ( low + high ) ;
//printf("mid--%d\n", mid) ;
if( state[i][mid] == x )
return mid ;
else if( state[i][mid] > x )
high = mid - 1 ;
else
low = mid + 1 ;
}
}
int main()
{
int t , n , i , j , k , l , x , y , temp ;
scanf("%d", &t) ;
while( t-- )
{
memset(num,0,sizeof(num)) ;
memset(dp1,-1,sizeof(dp1)) ;
memset(step,-1,sizeof(step)) ;
memset(dp2,-1,sizeof(dp2));
scanf("%d", &n) ;
for(i = 1 ; i <= n ; i++)
scanf("%s %d %d", p[i].s, &p[i].d, &p[i].c) ;
x = 1<<n ;
for(i = 0 ; i < x ; i++)
{
for(j = 0 , temp = 0 ; j < n ; j++)
if( (1<<j) & i )
temp++ ;
state[temp][ num[temp]++ ]= i ;
}
/*
for(i = 0 ; i <= n ; i++)
{
for(j = 0 ; j < num[i] ; j++)
printf("%d ", state[i][j]) ;
printf("\n") ;
}*/
dp1[0][0] = dp2[0][0] = 0 ;
for(i = 0 ; i < n ; i++)
{
for(j = 0 ; j < num[i] ; j++)
{
for(k = 1 ; k <= n ; k++)
{
if( 1<<(k-1) & state[i][j] )
continue ;
l = find1(state[i][j]+(1<<(k-1)),i+1) ;
//printf("l == %d\n", l ) ;
if( dp1[i+1][l] == -1 || ( dp1[i+1][l] > dp1[i][j] + max(dp2[i][j]+p[k].c-p[k].d,0) ) )
{
dp1[i+1][l] = dp1[i][j] + max(dp2[i][j]+p[k].c-p[k].d,0) ;
dp2[i+1][l] = dp2[i][j]+p[k].c ;
step[i+1][l] = j ;
}
}
}
}
/*for(i = 0 ; i <= n ; i++)
{
for(j = 0 ; j < num[i] ; j++)
printf("%d ", dp[i][j][0]) ;
printf("\n") ;
}*/
cnt = 0 ;
for(i = n , j = 0 ; i > 0 ; i--)
{
x = state[i][j] ;
y = state[i-1][ step[i][j] ] ;
//printf("x = %d y = %d\n", x, y) ;
for(k = 1 ; k <= n ; k++)
{
if( x % 2 != y % 2 )
break ;
x /= 2 ;
y /= 2 ;
}
c[cnt++] = k ;
j = step[i][j] ;
}
int min1 = dp1[n][0] ;
printf("%d\n", min1) ;
for(i = cnt - 1 ; i >= 0 ; i--)
printf("%s\n", p[c[i]].s ) ;
}
return 0 ;
}
原文:http://blog.csdn.net/winddreams/article/details/42586359