动态规划入门——Doing Homework

转载请注明出处:http://blog.csdn.net/a1dark

分析:这道题比较坑、本来可以贪心、但是题目要求按照字典序输出、由于贪心会打乱排序、所以不能用、然后是搜索、由于有N等于15、15!条路径、搜索也会超时、怎么优化呢、这是发现2<<15可以用数组装下、于是状压DP就出来了、转化成二进制之后1表示已经做了、0表示未做、目标状态是(1<<n)-1、

#include<stdio.h>
#include<string.h>
#include<algorithm>
using namespace std;
#define N 1<<15
#define INF 0xfffffff
struct node{
    int end,cost;
    char name[105];
}dot[N];
struct node1{
    int now,pre;
    int time,ans;
}dp[N];
int n,m;
void solve(){
    int next,time,ans;
    for(int i=1;i<=m;i++)
        dp[i].ans=INF;
    dp[0].time=0;
    for(int i=0;i<=m;i++){
        for(int j=0;j<n;j++){
            if(!(i&(1<<j))){
                next=i|(1<<j);
                time=dp[i].time+dot[j].cost;
                ans=max(0,time-dot[j].end);
                ans+=dp[i].ans;
                if(ans<dp[next].ans){//如果找到更优解
                    dp[next].time=time;
                    dp[next].ans=ans;
                    dp[next].now=j;
                    dp[next].pre=i;
                }
            }
        }
    }
}
void output(int x){
    if(x==0)return;
    output(dp[x].pre);
    printf("%s\n",dot[dp[x].now].name);
}
int main(){
    int t;
    scanf("%d",&t);
    while(t--){
        scanf("%d",&n);
        for(int i=0;i<n;i++)
            scanf("%s%d%d",&dot[i].name,&dot[i].end,&dot[i].cost);
        m=(1<<n)-1;
        solve();
        printf("%d\n",dp[m].ans);
        output(m);
    }
    return 0;
}


你可能感兴趣的:(ACM,动态规划入门)