Compress some of the recent status DP. DP bitter hand, from a simple start.

Http://acm.zju.edu.cn/onlinejudge/showProblem.do? Problemid = 1297

Zoj 2297

The question is to fight with N people in a round. You can choose the order of combat, and it will consume CI's physical strength. If the physical strength is less than 0 (note that it is less than or not greater than), it will fail, after hitting a person, the RI's physical strength will be restored. Ask you if there is an order in which you can finish the last person.

Obviously, the status compresses the DP, starting with Wa because of the problem of less than 0 (not scientific, who saw the game's HP reduced to 0 and it was still cool !), If DP [flag] is set to the maximum value of HP left when the hit person is in the flag status

DP [flag] = max (DP [flag ']-C [I] + R [I]) DP [flag ']> = C [I] and flag' = Flag ^ (1 <I), because the last person is fixed, therefore, we can compare the DP [flag] (here, flag indicates the status of all the people except the last one) and C [N]. The Code is as follows:

#include <iostream>#include <string.h>#include <algorithm>#include <stdio.h>using namespace std;int dp[1<<20];int c[21],r[21];int max(int a,int b){ return a>b?a:b;}int min(int a,int b){ return a<b?a:b;}int n;int dfs(int flag){ if(dp[flag]!=-1) return dp[flag]; int i; int ans=0; for(i=1;i<n;i++) { if(flag&(1<<(i-1))) { int tmp=dfs(flag^(1<<(i-1))); if(tmp>=c[i]) { ans=max(ans,min(100,tmp-c[i]+r[i])); } } } return dp[flag]=ans;}int main(){ //freopen("dd.txt","r",stdin); while(scanf("%d",&n)!=EOF) { int i; for(i=1;i<n;i++) { scanf("%d%d",&c[i],&r[i]); } scanf("%d",&c[n]); int limit=(1<<(n-1))-1; for(i=0;i<=limit;i++) dp[i]=-1; dp[0]=100; if(dfs(limit)>=c[n]) printf("clear!!!\n"); else printf("try again\n"); } return 0;}

Http://acm.zju.edu.cn/onlinejudge/showProblem.do? Problemid = 4345

Zoj 3502

It is also a very basic State compression DP, here as long as you know the expected value is to sum up the accuracy of each question. The maximum expectation is good. But I wa 7 times. Why? Because we need to find out the order of the questions, and the minimum Lexicographic Order of all evil words... Here DP [flag] indicates the maximum expectation of the question in this status (0 indicates that this question has not been viewed, 1 indicates that this question has been done, whether it is correct or not ). Ask for the maximum expectation after all the questions are done. DP [flag] is very helpful. I will not detail it here. It is a little troublesome to find the specific order. I am violent, if way [flag] is set, it indicates the smallest Lexicographic Order when the maximum expectation is reached in this state, and then the brute force update is performed. Today, this question is completely over to me .... The Code is as follows:

#include <iostream>#include <string.h>#include <algorithm>#include <stdio.h>using namespace std;int bo[10][10];char way[1<<10][10];int dp[1<<10];int n;int dfs(int flag){ if(dp[flag]!=-1) return dp[flag]; int i,j,k,num=0; int a[10]; for(i=0;i<n;i++) { if(flag&(1<<i)) { a[num++]=i; } } //printf("%d\n",num); int ans=-1,po; for(i=0;i<num;i++) { int tmp=0; int now=a[i]; for(j=0;j<num;j++) { if(bo[a[j]][now]>tmp) { tmp=bo[a[j]][now]; } } if(tmp+dfs(flag^(1<<now))>ans) { ans=tmp+dfs(flag^(1<<now)); strcpy(way[flag],way[flag^(1<<now)]); int len=strlen(way[flag]); way[flag][len]=now+'A'; way[flag][len+1]='\0'; po=now; } else if(tmp+dfs(flag^(1<<now))==ans) { if(strcmp(way[flag^(1<<now)],way[flag^(1<<po)])<0) { strcpy(way[flag],way[flag^(1<<now)]); int len=strlen(way[flag]); way[flag][len]=now+'A'; way[flag][len+1]='\0'; po=now; } } } return dp[flag]=ans;}int aa[10];int main(){ //freopen("dd.txt","r",stdin); int ncase; scanf("%d",&ncase); while(ncase--) { int i,j; scanf("%d",&n); for(i=0;i<n;i++) { for(j=0;j<n;j++) { scanf("%d",&bo[i][j]); } } int limit=(1<<n)-1; memset(dp,-1,sizeof(dp)); memset(way,'\0',sizeof(way)); dp[0]=0; int ans=dfs(limit); printf("%.2f\n",(double)ans/100); printf("%s\n",way[limit]); } return 0;}

Http://poj.org/problem? Id = 2923

Poj 2923

A person wants to move a house. There are two cars. The carrying capacity of the two cars is C1 and C2 respectively. Now I will give you the weight of each piece of furniture C [I], the furniture can be moved back and forth at least several times.

We set DP [0] [flag] to indicate how many times the First Furniture whose moving status is flag will be used at least (1 in the flag indicates moving the furniture, 0 indicates not to move). We can handle the second car similarly. If W [0] [flag] is set to W [0], it indicates that after the first car is finished, its maximum residual load. The status transfer becomes very obvious. For each status, we enumerate the furniture to be moved and set it to I (provided that the current status includes I ), the status before moving the I furniture is flag '= (flag ^ (1 <I )), if W [0] [flag ']> = C [I], DP [flag] = DP [flag'], otherwise, when DP [flag] = DP [flag '] + 1, we take the minimum value of DP [flag]. If the minimum value is the same, we must ensure that W [0] [flag] is the largest. After completing the evaluation, we calculate DP [0] [flag] and DP [1] [~ Flag] (here ~ Flag refers to the greater margin of the Flag), and then the smallest of these values can be removed. The Code is as follows:

#include <string.h>#include <algorithm>#include <stdio.h>#define inf 2100000000using namespace std;int dp[2][1<<10],left[2][1<<10],c[2],v[11];int n;int min(int a,int b){ return a<b?a:b;}int max(int a,int b){ return a>b?a:b;}int dfs(int flag,int t){ //printf("f"); if(dp[t][flag]!=-1) return dp[t][flag]; if(flag==0) { left[t][flag]=c[t]; return dp[t][flag]=1; } int i; int ans=inf,ll=0,num,le,tans,tleft; for(i=1;i<=n;i++) { if(flag&(1<<(i-1))) { int tmp=flag^(1<<(i-1)); num=dfs(tmp,t),le=left[t][tmp]; if(le<v[i]) { if(v[i]>c[t]) { left[t][flag]=0; return dp[t][flag]=inf; } else { tleft=c[t]-v[i]; tans=num+1; } } else { tleft=le-v[i]; tans=num; } if(tans<ans) { ans=tans; ll=tleft; } else if(tans==ans&&tleft>ll) { ll=tleft; } } } left[t][flag]=ll; return dp[t][flag]=ans;}int main(){ // freopen("dd.txt","r",stdin); int ncase,time=0; scanf("%d",&ncase); while(ncase--) { printf("Scenario #%d:\n",++time); memset(dp,-1,sizeof(dp)); scanf("%d%d%d",&n,&c[0],&c[1]); for(int i=1;i<=n;i++) scanf("%d",&v[i]); int limit=(1<<n)-1; int ans=inf; for(int i=0;i<=limit;i++) { int tmp=max(dfs(i,0),dfs(limit-i,1)); ans=min(ans,tmp); } printf("%d\n\n",ans); } return 0;}

Http://poj.org/problem? Id = 3229

Poj 3229

The question is erratic and difficult to grasp. I feel that 1y is actually a question similar to the TSP after creating a graph without looking at discuss, however, a point added to the question is that there is still a stay time on each node, and it should be noted that this question is returned from the origin point and only requires a stay time on the origin point, it is not necessary to access all vertices. Each vertex can go through countless times. Therefore, after creating a graph, we need to use Floyd for preprocessing. There is nothing else to talk about. In fact, the question is not difficult, the key is that the question is too vague, and people do not dare to do it. This question is similar to poj3311 (there is a http://blog.csdn.net/dyx404514/article/details/8758376 here), very simple state transfer, here it will not be repeated. The Code is as follows:

#include <iostream>#include <string.h>#include <algorithm>#include <stdio.h>#define inf 2100000000using namespace std;int n,m,k;double map[16][16];int time[16];double dp[15][1<<14];double min(double a,double b){ return a<b?a:b;}int max(int a,int b){ return a>b?a:b;}void floyd(){ int i,j,k; for(i=0;i<n;i++) { for(j=0;j<n;j++) { for(k=0;k<n;k++) { map[j][k]=min(map[j][i]+map[i][k],map[j][k]); } } }}int getnum(int x){ int sum=0; while(x) { sum+=x%2; x/=2; } return sum;}double dfs(int now,int flag){ if(dp[now][flag]>0) return dp[now][flag]; if((1<<(now-1))==flag) { if(map[0][now]==inf) return dp[now][flag]=inf; return dp[now][flag]=map[0][now]+time[now]; } double ans=inf; int i; for(i=1;i<n;i++) { if(i!=now&&((1<<(i-1))&flag)&&map[i][now]!=inf) { ans=min(ans,time[now]+map[i][now]+dfs(i,flag^(1<<(now-1)))); } } return dp[now][flag]=ans;}int main(){ // freopen("dd.txt","r",stdin); while(scanf("%d%d%d",&n,&m,&k)) { if(n==0&&m==0&&k==0) break; k*=12; int limit=0; int i,x,j; for(i=1;i<=m;i++) { scanf("%d",&x); if(x!=1) limit+=1<<(x-2); } memset(dp,0,sizeof(dp)); for(i=0;i<n;i++) { for(j=0;j<n;j++) map[i][j]=inf; } for(i=0;i<n;i++) { map[i][i]=0; scanf("%d",&time[i]); } int a,b,d,t; while(scanf("%d%d%d%d",&a,&b,&d,&t)) { if(a+b+d+t==0) break; if(t) { double tt=(double)d/120; if(map[a-1][b-1]>tt) map[a-1][b-1]=map[b-1][a-1]=tt; } else { double tt=(double)d/80; if(map[a-1][b-1]>tt) map[a-1][b-1]=map[b-1][a-1]=tt; } } floyd(); int tmp=(1<<(n-1))-1; int ans=-1; for(i=0;i<=tmp;i++) { if((i&limit)==limit) { for(j=1;j<n;j++) { if(map[j][0]!=inf&&(i&(1<<(j-1)))) { if(map[j][0]+dfs(j,i)+time[0]<=(double)k) { ans=max(ans,getnum(i)+1); } } } } } if(ans==-1) printf("No Solution\n"); else printf("%d\n",ans); } return 0;}