hdu(1074)Doing Homework

来源:互联网 发布:山西z证券交易软件 编辑:程序博客网 时间:2024/05/29 08:11

 

#include"stdio.h"
#include"string.h"
#include"stdlib.h"
#define inf 0x7fffffff
int hash[60000],used[1000];
int save[1000],temp[1000];
int m,n,ans;
struct point
{
 int name[200];
 int x,y;
}a[100];
void bfs(int k ,int state,int now,int sum,int cnt)
{
 int i;
 if(cnt==n)
 {
  if(sum<ans)
  {
   ans=sum;
   for(i=0;i<n;i++)
   {
    save[i]=temp[i];
   }
   return ;
  }
 }
 if(hash[state]!=-1&&sum>hash[state])
 {
  return ;
 }
 if(hash[state]==-1||sum<hash[state])
 {
  hash[state]=sum;
 }
 for(i=1;i<=n;i++)
 {
  if(used[i]==0)
  {
  int Now,Sum;
  if(now+a[i].y>a[i].x)
  {
   Sum=sum+now+a[i].y-a[i].x;
  }
  else
   Sum=sum;
  Now=now+a[i].y;
  used[i]=1;
  temp[cnt]=i;
  bfs(i,state+(1<<(i-1)),Now,Sum,cnt+1);
  used[i]=0;
  }
 }
}
int main()
{
 int m,i,j,k;
 scanf("%d",&k);
 while(k--)
 {
  scanf("%d",&n);
  ans=inf;
  memset(hash,-1,sizeof(hash));
  memset(used,0,sizeof(used));
  for(i=1;i<=n;i++)
   scanf("%s%d%d",a[i].name,&a[i].x,&a[i].y);
  bfs(0,0,0,0,0);
  printf("%d\n",ans);
  for(i=0;i<n;i++)
   printf("%s\n",a[save[i]].name);
 }
 return 0;
}

 

 

#include<stdio.h>
#include<string.h>
#define inf 0x3fffffff
struct node
{
char name[300];
int d;//截止日期  
int c;//需要花费日期
}hw[20];
struct point
{
int now,pre; //当前状态id,与过去状态id
int nowtime;//当前时间
int score;//当前最少花费
int key; //当前课程的id
}dp[40000];
int main()
{
int t,n,i,j,k,cur,preid,limit,temp;
char s[20][300];
scanf("%d",&t);
while(t--)
{
scanf("%d",&n);
limit=1<<n;
for(i=0;i<n;i++)
scanf("%s%d%d",hw[i].name,&hw[i].d,&hw[i].c);
dp[0].now=0; dp[0].nowtime=0;dp[0].score=0;
for(i=1;i<limit;i++)
{
dp[i].score=inf;
for(j=n-1;j>=0;j--)//注意j从n-1开始,因为这样的话,preid是个小值,初始化了。
{
cur=1<<j;
if(i&cur)
{
preid=i-cur;
if(dp[preid].nowtime+hw[j].c>hw[j].d)
    temp=dp[preid].nowtime+hw[j].c-hw[j].d;
else
temp=0;
if(dp[preid].score+temp<dp[i].score)
{
dp[i].score=dp[preid].score+temp;
dp[i].now=i;
dp[i].pre=preid;
dp[i].nowtime=dp[preid].nowtime+hw[j].c;
dp[i].key=j;
}
}
}
}
printf("%d\n",dp[limit-1].score);
k=limit-1;i=0;
while(dp[k].now!=0)
{
    strcpy(s[i++],hw[dp[k].key].name);
k=dp[k].pre;
}
for(j=i-1;j>=0;j--)
printf("%s\n",s[j]);
}
return 0;
}




这题有作业数的规定,有每一样作业的截止时间要求,有写每一样作业所需花费的时间,作业要按期完成,否则每超一天扣一分,问怎样才能让他扣分最少。
开始我想和其他dp一样找状态转移方程,但感觉他的状态要表示出来很困难。由于题目说作业数最多是15,因此若我们采用一个2的15次方的数来表示,每一个数为0则表示尚未完成此项作业,为1则表示已完成此项作业,这样这个状态就很好表示了。
在这里设置一个结构体,里面要包含一个记录前驱的pre,然后自然的有最小的扣分代价,此外,由于是否在规定时间内完成了这道题目是由当前时间,截止时间和你花费时间共同决定的,那你就必须判断当前时间与截止时间的差距是多少,因此外设一个表示当前时间。
以dp[i]来表示完成了i这个二进制数中所有为1的位置的对应的作业的状态(感觉有点绕..)
至于递推条件:(1)对当前状态i进行枚举他所为0的部分,j,若(i&j==0)则说明j这样作业尚未被完成。(2)然后将其添加,变成cell=i|j,在更新dp[cell]。在此我们要设一个标记数组,因为我们并不知道之前cell是否已经被更新。

#include<stdio.h>
#include<string.h>
#define inf 0x3fffffff
#define maxsize 1<<16
struct p
{
int mincost ; //最小的损失
int pre;//指向对应的前驱
int nowtime;//当前时间的进程
}dp[maxsize];//这个,是作为当前形成这种状态的一个对应数组
int vist[maxsize];
struct node
{
int deadline;
int cost;
char name[200];
}course[20];//这个是针对于课程的
void print(int k,int t)
{
int v,cnt=0;
v=(k^t);//这里采用异或操作找出对应的位置
while(v)
{
v=v>>1;
cnt++;
}
k=t;t=dp[t].pre;
if(t!=-1)
print(k,t);
printf("%s\n",course[cnt-1].name);
}
       
int main()
{
int t,i,j,n,limit,k,temp,cell,currt,subt,sum;
scanf("%d",&t);
while(t--)
{
scanf("%d",&n);
for(i=0;i<n;i++)
scanf("%s%d%d",course[i].name,&course[i].deadline,&course[i].cost);
limit=1<<n;//二进制表示的一个总体状态的数字
dp[0].nowtime=0;dp[0].mincost=0;dp[0].pre=-1;//初始化
for(i=1;i<n;i++)
dp[i].mincost=inf;
memset(vist,0,sizeof(vist));//初始化标记数组
//下面开始遍历进行找出最小的代价
for(i=0;i<limit;i++)//注意从0 开始
{
for(j=0;j<n;j++)
{
temp=1<<j;
if((temp&i)==0)
{//这种情况说明了当前这个j不在我们完成的课程里
cell=temp|i;//把这个j加入到了当前情况中
currt=dp[i].nowtime+course[j].cost;//把当前dp所走到的时间再加上要完成此课会消耗的时间
subt=currt-course[j].deadline;//求出此时此课的最小代价
if(subt<0)
subt=0;
sum=dp[i].mincost+subt;
if(vist[cell])//如果被访问过了
{
if(sum<dp[cell].mincost)
{
dp[cell].mincost=sum;
dp[cell].nowtime=currt;
dp[cell].pre=i;
}
}
else
{
dp[cell].mincost=sum;
dp[cell].pre=i;
dp[cell].nowtime=currt;
vist[cell]=1;
}
}
}
}
//由于代码中是只有当allsu<dp[cell].mincost才更新,因此按输入顺序必然是输出最小的那一个起
//扣分相同,取字典序小的那一个,由于这里j是按从小到大搜索的,默认已是按字典序,不需再处理
printf("%d\n",dp[limit-1].mincost);
k=limit-1;
j=dp[limit-1].pre;
print(k,j);
}
return 0;
}

#include<stdio.h>
#include<string.h>
#define inf 0x3fffffff
struct node
{
char name[200];
int d;
int c;
}hw[20];
struct p
{
int nowtime;
int pre;
int key;
int mincost;
}dp[1<<16];
int mark[1<<16];
int main()
{
int t,i,j,k,s,sum,cell,n,limit;
char str[20][200];
scanf("%d",&t);
while(t--)
{
scanf("%d",&n);
for(i=0;i<n;i++)
scanf("%s%d%d",hw[i].name,&hw[i].d,&hw[i].c);
limit=1<<n;
dp[0].nowtime=0;dp[0].pre=0;dp[0].mincost=0;
memset(mark,0,sizeof(mark));
for(i=1;i<=limit;i++)
dp[i].mincost=inf;
for(i=0;i<limit;i++)
{
for(j=0;j<n;j++)
{
int cur=1<<j;
if(!(cur&i))
{
cell=cur|i;
s=dp[i].nowtime+hw[j].c-hw[j].d;
if(s<0)
s=0;
sum=dp[i].mincost+s;
if(mark[cell])
{
if(dp[cell].mincost>sum)
{
dp[cell].mincost=sum;
dp[cell].nowtime=dp[i].nowtime+hw[j].c;
dp[cell].pre=i;
dp[cell].key=j;
}
}
else
{
   dp[cell].mincost=sum;
dp[cell].nowtime=dp[i].nowtime+hw[j].c;
dp[cell].pre=i;
dp[cell].key=j;
mark[cell]=1;
}
}
}
}
printf("%d\n",dp[limit-1].mincost);
k=limit-1;i=0;
while(dp[k].nowtime!=0)
{
    strcpy(str[i++],hw[dp[k].key].name);
k=dp[k].pre;
}
for(j=i-1;j>=0;j--)
printf("%s\n",str[j]);
}
return 0;
}



 

原创粉丝点击