hdu 1074
阿新 • • 發佈:2018-05-04
acm狀態壓縮題,要註意的是有多種情況扣分相同,那麽要按照字典序輸出,也就是輸入時在前,那麽輸出也要在前。具體看代碼註釋。
參考文章:
參考文章:
- http://www.voidcn.com/article/p-fsgosnqv-bpb.html
- http://www.cnblogs.com/kuangbin/archive/2011/08/04/2127687.html
- http://www.cnblogs.com/qkhhxkj/archive/2011/06/29/2093894.html
#include <iostream> #include <stdio.h> #include <string> #include <stack> using namespace std; const int maxn=1<<17; struct homework{ char name[150]; int deadline; int timecost;//做作業所花費的時間 }h[30]; struct node{ int score;//當前的扣分情況 int time;//當前所花的天數 int num;//當前所做作業的序號 int pre;//上一個狀態的地址 }dp[maxn];//數組要開的足夠大,數字上限為2^n int main(){ int T,N; scanf("%d",&T); while(T--){ scanf("%d",&N); for(int i=0;i<N;i++) scanf("%s%d%d",&h[i].name,&h[i].deadline,&h[i].timecost); dp[0].score=0; dp[0].time=0; int M=(1<<N)-1; for(int i=1;i<=M;i++){//用二進制的0~n-1位來表示作業1~n的完成情況,0為都沒有完成,(1<<N)-1表示所有作業都完成,這裏進行遍歷 dp[i].score=100000;//保證dp[i]得到初始化 for(int j=N-1;j>=0;j--){//j從大到小每個作業遍歷,保證字典序輸出 int temp=1<<j; if((i&temp)==temp){//表示當前作業狀態是做了j號作業的 int k=i-temp;//表示上一個狀態,也就是沒有做j號作業,其余與這個狀態一樣 int x=dp[k].time+h[j].timecost-h[j].deadline; if(x<0) x=0;//計算做j號作業是否逾期,若沒有預期逾期則不扣分 if(dp[k].score+x<dp[i].score){//若為扣分最少的情況,則更改信息 dp[i].score=dp[k].score+x; dp[i].num=j; dp[i].time=dp[k].time+h[j].timecost; dp[i].pre=k; } } } } printf("%d\n",dp[M].score); stack<int>st; while(M!=0){ st.push(dp[M].num); M=dp[M].pre; } while(!st.empty()){ printf("%s\n",h[st.top()].name); st.pop(); } } return 0; }
確實不是很懂這題,出錯的地方請見諒。
hdu 1074