最近真是太水啦,就拿昨天的比赛来说,只过了一道。。。,最后一道因为一个变量写反啦,一直WA到比赛结束,直接导致我没有看到1002这道大水题。。。唉,看来我真不是比赛型选手,今天把1005和1002做了下,补个题解吧。
http://acm.hdu.edu.cn/showproblem.php?pid=4535
吉哥还是那个吉哥
那个江湖人称“叽叽哥”的基哥
每当节日来临,女友众多的叽叽哥总是能从全国各地的女友那里收到各种礼物。
有礼物收到当然值得高兴,但回礼确是件麻烦的事!
无论多麻烦,总不好意思收礼而不回礼,那也不是叽叽哥的风格。
现在,即爱面子又抠门的叽叽哥想出了一个绝妙的好办法:他准备将各个女友送来的礼物合理分配,再回送不同女友,这样就不用再花钱买礼物了!
假设叽叽哥的n个女友每人送他一个礼物(每个人送的礼物都不相同),现在他需要合理安排,再回送每个女友一份礼物,重点是,回送的礼物不能是这个女友之前送他的那个礼物,不然,叽叽哥可就摊上事了,摊上大事了......
现在,叽叽哥想知道总共有多少种满足条件的回送礼物方案呢?
1001:有公式的,亏我还推了半天,数据量也不大,直接根据公式推就行,水题就不说了。。。
http://acm.hdu.edu.cn/showproblem.php?pid=4536
#include <iostream> #include <string.h> #include <stdio.h> #include <algorithm> #define maxn 100010 #include <vector> using namespace std; int ask[110][3]; int aa[20]; int v[20]; int t[6][110]; int len[6]; int k; int dfs(int num) { if(num>k) return 0; int i,j,ans=0; for(i=0;i<3;i++) { int a=ask[num][i],b=ask[num][(i+1)%3],c=ask[num][(i+2)%3]; if(aa[b]>3||aa[c]>3) continue; int tru=1,sum=len[v[b]]; for(j=0;j<sum;j++) { if(aa[t[v[b]][j]]==5) { tru=0;break; } } if(!tru) continue; sum=len[v[c]]; for(j=0;j<sum;j++) { if(aa[t[v[c]][j]]==5) { tru=0;break; } } if(!tru) continue; sum=len[v[c]]; for(j=0;j<sum;j++) { aa[t[v[c]][j]]++; } sum=len[v[b]]; for(j=0;j<sum;j++) { aa[t[v[b]][j]]++; } aa[b]++; aa[c]++; int tmp=aa[a]; aa[a]=max(1,aa[a]-2); ans=max(ans,max(num,dfs(num+1))); sum=len[v[c]]; for(j=0;j<sum;j++) { aa[t[v[c]][j]]--; } sum=len[v[b]]; for(j=0;j<sum;j++) { aa[t[v[b]][j]]--; } aa[b]--; aa[c]--; aa[a]=tmp; } return ans; } int main() { freopen("dd.txt","r",stdin); int ncase,time=0; scanf("%d",&ncase); while(ncase--) { int n,m,i; printf("Case #%d: ",++time); scanf("%d%d%d",&n,&m,&k); memset(len,0,sizeof(len)); for(i=0;i<n;i++) { scanf("%d",&v[i]); t[v[i]][len[v[i]]++]=i; } for(i=0;i<n;i++) scanf("%d",&aa[i]); for(i=1;i<=k;i++) scanf("%d%d%d",&ask[i][0],&ask[i][1],&ask[i][2]); int ans=dfs(1); printf("%d\n",ans); } return 0; }
http://acm.hdu.edu.cn/showproblem.php?pid=4539
郑厂长不是正厂长
也不是副厂长
他根本就不是厂长
事实上
他是带兵打仗的团长
一天,郑厂长带着他的军队来到了一个n*m的平原准备布阵。
根据以往的战斗经验,每个士兵可以攻击到并且只能攻击到与之曼哈顿距离为2的位置以及士兵本身所在的位置。当然,一个士兵不能站在另外一个士兵所能攻击到的位置,同时因为地形的原因平原上也不是每一个位置都可以安排士兵。
现在,已知n,m 以及平原阵地的具体地形,请你帮助郑厂长计算该阵地,最多能安排多少个士兵。
1005:这是昨天的啃死爹题,因为一个傻逼错误WA到最后。。。这道题一般人一看就知道是状态压缩DP了吧,但是我不是一般人啊,我是大傻X啊,就是只会往最大独立集去想啊。。。然后还没想出来啊。。。
经典的状态压缩DP,我这DP水货遇到DP就怂。。。我们设dp[i][pre][now]表示第i行为now状态,第i-1行为pre状态时可以安排的最大士兵数量,这里的状态指的是每一行的士兵安排情况,我们把状态用二进制表示出来后,第i位为1表示在第i列放置一个士兵,为0表示不放,因为m<=10所以我们最多只要1024个状态就可以表示一行的每一个状态,事实上这1024个状态中有大部分是不合法的,(也就是有两个1其距离为2),所以我们可以预处理出所有的合法状态,(我们下面所讨论的状态都是合法的),对于dp[i][pre][now]我要怎么计算呢?
首先当然是这两个状态不能和所给的矩阵有冲突(也就是在不能人的地方放置了人),然后相邻两行不能有距离为2的1存在。满足上面的条件后,则dp[i][pre][now]=max(dp[i-1][ppre][pre]),其中ppre也要状态也要满足以上条件。我们最后求合法状态中的最大值即可,以上快速判断是否满足要求可以用位运算来判断,具体如何用请自己思考,或者参考我的代码。
#include <iostream> #include <string.h> #include <algorithm> #include <stdio.h> #include <vector> using namespace std; int dp[200][200][200]; vector<int> a[11]; int check(int x,int len) { int i; for(i=0;i<len-2;i++) { int tmp=(1<<i)+(1<<(i+2)); if((tmp&x)==tmp) { return 0; } } return 1; } int cot[1100]; int getnum(int x) { int sum=0; while(x) { if(x%2) sum++; x/=2; } return sum; } void init() { int i,j,tmp; for(i=0;i<=1024;i++) cot[i]=getnum(i); for(i=1;i<=10;i++) { tmp=(1<<i)-1; a[i].push_back(0); for(j=1;j<=tmp;j++) { if(check(j,i)) { a[i].push_back(j); } } } } int max(int a,int b) { return a>b?a:b; } int num[110]; int main() { init(); int n,m,x; while(scanf("%d%d",&n,&m)!=EOF) { memset(dp,0,sizeof(dp)); int i,j,tmp; for(i=1;i<=n;i++) { tmp=0; for(j=1;j<=m;j++) { scanf("%d",&x); tmp=tmp*2+x; } num[i]=tmp; } tmp=a[m].size(); int ans=0; for(i=0;i<tmp;i++) { if((num[1]|a[m][i])==num[1])//判断是否满足棋盘 { int now=a[m][i]; dp[1][0][i]=cot[now]; ans=max(ans,dp[1][0][i]); } } for(i=2;i<=n;i++) { for(j=0;j<tmp;j++) { if((num[i]|a[m][j])==num[i])//状态满足第i行 { int now=a[m][j]; int s,t; for(s=0;s<tmp;s++) { int pre=a[m][s]; if((num[i-1]|pre)==num[i-1]) { if(((now<<1)&pre)==0&&((now>>1)&pre)==0) { if(i==2) dp[i][s][j]=dp[1][0][s]+cot[now]; else { for(t=0;t<tmp;t++) { int ppre=a[m][t]; if((num[i-2]|ppre)==num[i-2]) { if((ppre&now)==0) { if(((ppre<<1)&pre)==0&&((ppre>>1)&pre)==0) dp[i][s][j]=max(dp[i][s][j],dp[i-1][t][s]+cot[now]); } } } } ans=max(ans,dp[i][s][j]); } } } } } } printf("%d\n",ans); } return 0; }